我有一个带有以下代码的 MVVM WPF 项目:
MultiplexerVM.cs
public class MultiplexerVM : BaseViewModel
{
public ObservableCollection<MultiplexVM> Multiplexes { get; set; } = new();
public MultiplexVM SelectedMultiplex { get; set; }
public ICommand CheckAll => new CheckBoxCommand(Multiplexes);
}
MultiplexVM.cs
public class MultiplexVM : BaseViewModel
{
public bool IsChecked { get; set; }
}
多路复用器V.xaml
<UserControl x:Class="MKVStudio.Views.MultiplexerV"
xmlns:vm="clr-namespace:MKVStudio.ViewModels"
xmlns:s="clr-namespace:System;assembly=mscorlib">
<UserControl.Resources>
<s:Boolean x:Key="True">True</s:Boolean>
<s:Boolean x:Key="False">False</s:Boolean>
</UserControl.Resources>
<Grid>
<ListView ItemsSource="{Binding Multiplexes}"
SelectedItem="{Binding SelectedMultiplex}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked}"Margin="3"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
...
</GridView>
</ListView.View>
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Command="{Binding CheckAll}"
CommandParameter="{StaticResource True}">
<MenuItem.Header>
<TextBlock Text="Check all"/>
</MenuItem.Header>
</MenuItem>
<MenuItem Command="{Binding CheckAll}"
CommandParameter="{StaticResource False}">
<MenuItem.Header>
<TextBlock Text="Uncheck all"/>
</MenuItem.Header>
</MenuItem>
</ContextMenu>
</ListView.ContextMenu>
</ListView>
</Grid>
</UserControl>
我的目标是结合IsEnabled
背景关系选单项的财产IsChecked
的MultiplexVM.cs
。这个想法是实作一个IValueConverter
(passing Multiplexes
asvalue
和 bool as parameter
)。转换器回传value.Where(m => m.IsChecked == parameter).Count > 0
。本质上,当所有Multiplexes
都取消选中时,选单项Check all
被启用而选单项Uncheck all
被禁用。当所有Multiplexes
都被检查时,相反的事情正在发生。这里的问题是转换器在基本宣告时只被呼叫一次,检查和取消选中项目不会触发转换器查看发生了什么。
我试图实作一个IMultiValueConverter
(但未能正确使用它)并传递三个这样的值:
<MenuItem.IsEnabled>
<MultiBinding>
<Binding Source="{Binding Multiplexes.Count}" />
<Binding Source="{Binding Multiplexes}" />
<Binding Source="{StaticResource True}" /> <!--respectivly False to the other menu item-->
</MultiBinding>
</MenuItem.IsEnabled>
这不起作用。我试过<Binding Path="Multiplexes.Count" />
和<Binding Path="Multiplexes" />
,但也不起作用(传递给转换器的值为Unset
)。
我MultiBinding
使用它的想法是否可行,使用它时我做错了什么?
uj5u.com热心网友回复:
为什么需要同时将 IsChecked 系结到 IsChecked 和 IsEnabled?如果从单一职责原则来看,这很奇怪。如果你确定你做对了,你可以这样做:
<CheckBox IsChecked="{Binding IsChecked}"
IsEnabled="{Binding IsEnabled}" />
让你的班级看起来像这样:
public class MultiplexVM : BaseViewModel
{
public bool IsChecked
{
get => isChecked;
set
{
isChecked = value;
isEnabled = value;
RaisePropertyChanged(nameof(IsChecked));
RaisePropertyChanged(nameof(IsEnabled));
};
}
private bool isChecked;
public bool IsEnabled
{
get => isEnabled;
set
{
isChecked = value;
isEnabled = value;
RaisePropertyChanged(nameof(IsChecked));
RaisePropertyChanged(nameof(IsEnabled));
};
}
private bool isChecked;
}
uj5u.com热心网友回复:
据我了解,您想让系结到“父”的物件(MenuItem => MultiplexerVM)
依赖于其子集合的属性(CheckBox => MultiplexVM.IsChecked
,它是 中的一个项目MultiplexerVM.Multiplexes
)
在这种情况下,子级必须以某种方式知道其父级(当子级更改时,它必须将更改“推送”给父级;换句话说,必须在发生更改时通知父级)。
我可以想到两种方法来做到这一点:
在 VM 级别:在 every 中
MultiplexVM
,设定对父视图模型或集合的参考,然后您可以在CanCheckAll / CanUncheckAll
每次孩子IsChecked
更改时更新功能(无论您如何实作它)(乏味;我想您也可以使用事件来执行此操作,但是将PropertyChanged
处理程序附加到每个子项也有点多)通过使用 GUI 级别作弊:您可以
CanCheckAll / CanUncheckAll
在CheckBox
单击时更新功能
下面是如何实作第二个版本的示例。
在您的MultiplexerVM
:
public bool CanCheckAll => Multiplexes.Any(a => !a.IsChecked);
public bool CanUncheckAll => Multiplexes.Any(a => a.IsChecked);
public void RefreshCheckUncheckAll()
{
NotifyPropertyChanged(nameof(CanCheckAll));
NotifyPropertyChanged(nameof(CanUncheckAll));
}
然后,呼叫RefreshCheckUncheckAll()
的CheckAll
命令执行情况和:
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
((MultiplexerVM)this.DataContext).RefreshCheckUncheckAll();
}
然后,xaml 将如下所示:
<ListView ItemsSource="{Binding Multiplexes}" SelectedItem="{Binding SelectedMultiplex}">
<ListView.ContextMenu>
<ContextMenu>
<MenuItem
Command="{Binding CheckAll}"
CommandParameter="{StaticResource True}"
IsEnabled="{Binding CanCheck}">
<MenuItem.Header>
<TextBlock Text="Check all" />
</MenuItem.Header>
</MenuItem>
<MenuItem
Command="{Binding CheckAll}"
CommandParameter="{StaticResource False}"
IsEnabled="{Binding CanUncheck}">
<MenuItem.Header>
<TextBlock Text="Uncheck all" />
</MenuItem.Header>
</MenuItem>
</ContextMenu>
</ListView.ContextMenu>
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Margin="3" Text="{Binding Name}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Margin="3" IsChecked="{Binding IsChecked}" Click="CheckBox_Click" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
0 评论