首页 > 解决方案 > 如何在 ViewModel 中使用数组?

问题描述

我的代码现在看起来像这样,每条消息都有两行代码。该代码有效,但如果我有例如 30 条消息,我可以为每条消息赋予值,那么我将需要 60 行代码来声明所有内容:

string _msg1;
string _msg2;
public string Msg1 { get => _msg1; set => SetProperty(ref _msg1, value); }
public string Msg2 { get => _msg2; set => SetProperty(ref _msg2, value); }

在 C# 中我分配给这些:

vm.Msg1 = "A";
vm.Msg2 = "B"; 

在 XAML 中,我将我的 Text 绑定到 Msg1,将另一个 Text 绑定到 Msg2

有人可以告诉我如何/如果我可以用数组执行此操作,以便我可以像这样分配,并希望数组的分配可以在两行而不是每条消息的两行中完成:

vm.Msg[0] = "A";
vm.Msg[1] = "B";

以供参考:

public class ObservableObject : INotifyPropertyChanged
{

    protected virtual bool SetProperty<T>(
        ref T backingStore, T value,
        [CallerMemberName]string propertyName = "",
        Action onChanged = null)
    {
        if (EqualityComparer<T>.Default.Equals(backingStore, value))
            return false;

        backingStore = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = "") =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

}

标签: c#asp.netasp.net-mvcxamarinxamarin.forms

解决方案


您可以使用支持属性更改通知的索引创建一个简单的包装类。

例如:

public class Messages : ObservableObject
{
    readonly IDictionary<int, string> _messages = new Dictionary<int, string>();

    [IndexerName("Item")] //not exactly needed as this is the default
    public string this[int index]
    {
        get
        {
            if (_messages.ContainsKey(index))
                return _messages[index];

//Uncomment this if you want exceptions for bad indexes
//#if DEBUG
//          throw new IndexOutOfRangeException();
//#else
            return null; //RELEASE: don't throw exception
//#endif
        }

        set
        {
            _messages[index] = value;
            OnPropertyChanged("Item[" + index + "]");
        }
    }
}

并且,在视图模型中创建一个属性:

private Messages _msg;
public Messages Msg
{
    get { return _msg ?? (_msg = new Messages()); }
    set { SetProperty(ref _msg, value); }
}

现在您可以将值设置或更新为:

vm.Msg[0] = "A";
vm.Msg[1] = "B";

XAML 中的绑定将与以下内容相同:

<Label Text="{Binding Msg[0]}" />
<Label Text="{Binding Msg[1]}" />

示例使用代码

XAML

<StackLayout Margin="20">
    <Label Text="{Binding Msg[0]}" />
    <Label Text="{Binding Msg[1]}" />
    <Label Text="{Binding Msg[2]}" />
    <Label Text="{Binding Msg[3]}" />
    <Label Text="{Binding Msg[4]}" />

    <Button Text="Trigger update" Command="{Binding UpdateMessage}" />
</StackLayout>

代码隐藏,视图模型

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        var viewModel = new MainViewModel();

        viewModel.Msg[0] = "Original message 1";
        viewModel.Msg[1] = "Original message 2";
        viewModel.Msg[2] = "Original message 3";
        viewModel.Msg[3] = "Original message 4";
        viewModel.Msg[4] = "Original message 5";

        BindingContext = viewModel;
    }
}

public class MainViewModel : ObservableObject
{
    private Messages _msg;
    public Messages Msg
    {
        get { return _msg ?? (_msg = new Messages()); }
        set { SetProperty(ref _msg, value); }
    }

    public ICommand UpdateMessage => new Command(() =>
           {
               Msg[2] = "New message 3";
               Msg[0] = "New message 1";
           });
}

在此处输入图像描述


推荐阅读