如何在ViewModel中使用数组?

Ala*_*an2 6 c# asp.net asp.net-mvc xamarin xamarin.forms

我的代码现在看起来像这样,每条消息有两行代码.代码可以工作,但如果我有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); }
Run Code Online (Sandbox Code Playgroud)

在C#中我分配给这些:

vm.Msg1 = "A";
vm.Msg2 = "B"; 
Run Code Online (Sandbox Code Playgroud)

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

有人可以告诉我如何/如果我可以用数组这样做,所以我会这样分配,希望所以数组的分配可以只用两行代替每行消息2行:

vm.Msg[0] = "A";
vm.Msg[1] = "B";
Run Code Online (Sandbox Code Playgroud)

以供参考:

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));

}
Run Code Online (Sandbox Code Playgroud)

Lad*_*gic 7

数组不会引发属性更改事件.ObservableCollection当集合发生变化时,您需要使用可以引发事件的事件.但是,当集合中的对象更改了它的值时,这不会引发事件.您需要将对象(在本例中为字符串)包装为可以引发属性更改事件的类型.

像下面这样的东西会起作用:

    public class BindableValue<T> : INotifyPropertyChanged
    {
        private T _value;
        public T Value
        { get => _value; set => SetProperty(ref _value, value); }
        // INotifyPropertyChanged and SetProperty implementation goes here
    }

    private ObservableCollection<BindableValue<string>> _msg;
    public ObservableCollection<BindableValue<string>> Msg
    { get => _msg; set => SetProperty(ref _msg1, value); }
Run Code Online (Sandbox Code Playgroud)

你会结合Msg[0].Value,Msg[1].Value等等,

  • 使用SetProperty编辑.我建议在基类中实现INotifyPropertyChanged并重用它们而不是重写.或者,如果您仍处于项目的初期阶段,我建议您查找为您执行此操作的现有MVVM框架.我最喜欢的是Prism. (3认同)

Sha*_*raj 6

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

例如:

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 + "]");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

vm.Msg[0] = "A";
vm.Msg[1] = "B";
Run Code Online (Sandbox Code Playgroud)

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

<Label Text="{Binding Msg[0]}" />
<Label Text="{Binding Msg[1]}" />
Run Code Online (Sandbox Code Playgroud)

样本使用代码

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>
Run Code Online (Sandbox Code Playgroud)

代码隐藏,视图模型

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";
           });
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述