c# - 如何在 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));
}
解决方案
您可以使用支持属性更改通知的索引创建一个简单的包装类。
例如:
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";
});
}
推荐阅读
- sql - 从慢速源最佳实践加载数据
- python - 在 python 3.7 中将文字'"\n"'写入文档文件时出现问题
- c# - C# FTP File Download Error, "Access denied to D:\dd folder"
- javascript - 如何定义包含要在 HTML 中执行的方法的 JS 文件
- regex - Perl中的正则表达式对于相同的约束具有不同的逻辑
- ios - AVPlayer 视频在从 url iOS 解码视频数据包时冻结
- flutter - ListView.separated() 尝试从中删除项目时出错
- amazon-web-services - UnexpectedValueException “...不是 zip 存档”与作曲家
- cordova - 命令“cordova platform add Android --save”不起作用
- java - BroadcastReceiver 和 FLAG_INCLUDE_STOPPED_PACKAGES