使用 ReactiveUI wpf 无法将视图模型中的枚举值列表绑定到视图中的组合框
Using ReactiveUI wpf unable to bind List of Enum values from viewmodel to combobox in view
假设我有这个枚举
public enum LogType
{
None = 0,
File = 1,
Folder = 2
}
我看到了这个组合框
<ComboBox Name="CustomLogLogType" FontSize="10"
MinHeight="20" Height="20" SelectedItem="{Binding LogType}">
然后像这样的 ViewModel
public class CustomLogRuleItemViewModel : ReactiveObject
{
[Reactive]
public LogType LogType { get; set; } = LogType.File;
public List<LogType> LogTypes => Enum.GetValues(typeof(LogType)).Cast<LogType>().Where(_ => _ != LogType.None).ToList();
}
然后在视图的代码后面
public partial class CustomLogRuleItemView : ReactiveUserControl<CustomLogRuleItemViewModel>
{
public CustomLogRuleItemView()
{
InitializeComponent();
this.ViewModel = new CustomLogRuleItemViewModel();
this.DataContext = this.ViewModel;
//The below works
//CustomLogLogType.ItemsSource = this.ViewModel.LogTypes;
this.WhenActivated(
disposables =>
{
//If I use below it will error with exception
this.OneWayBind(this.ViewModel,
_ => _.LogTypes, _ => _.CustomLogLogType.ItemsSource)
.DisposeWith(disposables);
});
}
}
基本上如果我在下面绑定就可以了
CustomLogLogType.ItemsSource = this.ViewModel.LogTypes;
但是如果我尝试使用 ReactiveUI 进行如下绑定
this.OneWayBind(this.ViewModel,
_ => _.LogTypes, _ => _.CustomLogLogType.ItemsSource)
.DisposeWith(disposables);
我收到一个异常,指出 ReactiveUI.IViewFor 上的 LogType 违反了类型 'T' 的约束。不确定为什么我会得到一些关于 IViewFor 的争论,因为这只与视图的 ViewModel 实现有关。
问题是 ReactiveUI 默认情况下会通过解析 IViewFor<TypeInItemsSource>
来设置 ItemTemplate
,这意味着更容易拆分您的视图。因此,如果您在这些场景中添加 ItemTemplate、DisplayMemberPath 或 ItemTemplateSelector,自动视图查找将被关闭。有关执行此操作的代码行,请参阅 this code。
<ComboBox Name="CustomLogLogType" FontSize="10"
MinHeight="20" Height="20">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
我可以通过添加自己的 ItemTemplate 来解决这个问题。
我认为这实际上是一个错误,所以如果您不介意在 https://github.com/reactiveui/ReactiveUI/issues 打开一个错误,我会在接下来的几天内修复它。我不认为我们应该为原始类型添加 ItemTemplate,因为实际上我没有看到用户真的想要原始类型的这个功能。
假设我有这个枚举
public enum LogType
{
None = 0,
File = 1,
Folder = 2
}
我看到了这个组合框
<ComboBox Name="CustomLogLogType" FontSize="10"
MinHeight="20" Height="20" SelectedItem="{Binding LogType}">
然后像这样的 ViewModel
public class CustomLogRuleItemViewModel : ReactiveObject
{
[Reactive]
public LogType LogType { get; set; } = LogType.File;
public List<LogType> LogTypes => Enum.GetValues(typeof(LogType)).Cast<LogType>().Where(_ => _ != LogType.None).ToList();
}
然后在视图的代码后面
public partial class CustomLogRuleItemView : ReactiveUserControl<CustomLogRuleItemViewModel>
{
public CustomLogRuleItemView()
{
InitializeComponent();
this.ViewModel = new CustomLogRuleItemViewModel();
this.DataContext = this.ViewModel;
//The below works
//CustomLogLogType.ItemsSource = this.ViewModel.LogTypes;
this.WhenActivated(
disposables =>
{
//If I use below it will error with exception
this.OneWayBind(this.ViewModel,
_ => _.LogTypes, _ => _.CustomLogLogType.ItemsSource)
.DisposeWith(disposables);
});
}
}
基本上如果我在下面绑定就可以了
CustomLogLogType.ItemsSource = this.ViewModel.LogTypes;
但是如果我尝试使用 ReactiveUI 进行如下绑定
this.OneWayBind(this.ViewModel,
_ => _.LogTypes, _ => _.CustomLogLogType.ItemsSource)
.DisposeWith(disposables);
我收到一个异常,指出 ReactiveUI.IViewFor 上的 LogType 违反了类型 'T' 的约束。不确定为什么我会得到一些关于 IViewFor 的争论,因为这只与视图的 ViewModel 实现有关。
问题是 ReactiveUI 默认情况下会通过解析 IViewFor<TypeInItemsSource>
来设置 ItemTemplate
,这意味着更容易拆分您的视图。因此,如果您在这些场景中添加 ItemTemplate、DisplayMemberPath 或 ItemTemplateSelector,自动视图查找将被关闭。有关执行此操作的代码行,请参阅 this code。
<ComboBox Name="CustomLogLogType" FontSize="10"
MinHeight="20" Height="20">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
我可以通过添加自己的 ItemTemplate 来解决这个问题。
我认为这实际上是一个错误,所以如果您不介意在 https://github.com/reactiveui/ReactiveUI/issues 打开一个错误,我会在接下来的几天内修复它。我不认为我们应该为原始类型添加 ItemTemplate,因为实际上我没有看到用户真的想要原始类型的这个功能。