我正在做我的第一个WPF项目。 我的 UI 需要更具交互性。我有 2 个视图模型。主窗口视图模型和世界视图模型。
MainWindow xaml 简化代码:
<Window>
[...]
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
<Grid>
<!--Worlds combobox-->
<ComboBox Margin="2 0 0 0" MinWidth="100" IsEnabled="{Binding IsWorldsComboEnabled}"
ItemsSource="{Binding WorldViewModel.Worlds}" SelectedValue="{Binding WorldViewModel.CurrentWorld}"
DisplayMemberPath="Name"/>
</Grid>
</Window>
MainWindowViewModel.cs code:
public class MainWindowViewModel : BaseViewModel
{
public WorldViewModel WorldViewModel { get; set; }
public bool IsWorldsComboEnabled => WorldViewModel.Worlds != null;
/// <summary>
/// Default constructor
/// </summary>
public MainWindowViewModel()
{
WorldViewModel = WorldViewModel.Instance;
}
}
世界观模型.cs代码:
public class WorldViewModel : BaseViewModel
{
public ObservableCollection<World> Worlds { get; set; }
public World CurrentWorld { get; set; }
public static WorldViewModel Instance { get; set; }
// Called on startup
public static void Initialize()
{
Instance = new WorldViewModel();
}
/// <summary>
/// Default constructor
/// </summary>
public WorldViewModel()
{
}
}
ViewModels有点大,但这是最低需要的代码。BaseViewModel
是一个类,它通过 NuGet 包提供 NotifyPropertyChangedPropertyChanged.Fody
接口。
当"可观察集合"为空时Worlds
必须禁用我的ComboBox
。当IsWorldsComboEnabled
位于WorldViewModel
时,它运行良好,但我觉得这不是一种方式。多个视图将取决于WorldViewModel
但它们不需要IsWorldsComboEnabled
属性。所以它的地方在MainWindowViewModel
.
当WorldViewModel
的财产发生变化时,有什么方法可以通知MainWindowViewModel
吗?
以下代码行的问题在于,即使更改了WorldViewModel.Worlds
,也永远不会执行IsWorldsComboEnabled
的 setter,因此不会调用您的PropertyChangedEventHandler
。
public bool IsWorldsComboEnabled => WorldViewModel.Worlds != null
您可能会更改为public bool IsWorldsComboEnabled { get; set; }
并计算以下表达式
IsWorldsComboEnabled = WorldViewModel.Worlds != null;
每当您更改属性 WorldViewModel.Worlds 时。
在您的情况下,如果属性是ObservableCollection
,则可以注册到 CollectionChanged 事件
WorldViewModel.Worlds.CollectionChanged += MyCollectionChangedMethod;
并计算那里的表达式
private void MyCollectionChangedMethod(object sender, NotifyCollectionChangedEventArgs e)
{
IsWorldsComboEnabled = WorldViewModel.Worlds != null;
}