我使用MVVM模式。
有两个ViewModel:
ClientViewModel 和 DiskViewModel ,ClientViewModel有一个集合ObservableCollection<DiskViewModel>
。
我想展示他们的等级关系,并通过他们的ContextMenu
做一些事情。我在ContextMenu
TypeToBooleanConverter
中通过DataTrigger
设置了不同的TreeViewItem
,如下所示:
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<DataTrigger Value="true" Binding="{Binding Converter={cvt:TypeToBooleanConverter},ConverterParameter={x:Type vm:ClientViewModel}}">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Client"/>
</ContextMenu>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
但是有一个问题:
如果我仅通过上述方法为 ClientViewModel 设置ContextMenu
,而不是为 DiskViewModel 设置ContextMenu
,则会显示&#34;客户机&#34;如果右键单击磁盘TreeViewItem
。但我从来没有说过。
有了图片:这不是我需要的。如果我右键单击磁盘TreeViewItem
,我什么都不想要。
上面的场景是最简单的。实际上等级关系就是:
ClientList
|---Client
|---DiskList
|---Disk
|---PartitionList
|---Partition
不同类型的项目或具有不同状态的一种类型时间具有不同的ContextMenu。列举所有案例可能是一项重要的工作。
我需要你的帮助。
代码文件:
// MainViewModel.cs
using GalaSoft.MvvmLight;
using System.Collections.ObjectModel;
namespace WpfApplication12.ViewModel
{
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
ClientList = new ObservableCollection<ClientViewModel>();
var disk = new DiskViewModel();
disk.Name = "disk1";
var client = new ClientViewModel();
client.Name = "client1";
client.DiskList.Add(disk);
ClientList.Add(client);
}
#region ClientList
public const string ClientListPropertyName = "ClientList";
private ObservableCollection<ClientViewModel> _clientList;
public ObservableCollection<ClientViewModel> ClientList
{
get
{
return _clientList;
}
set
{
if (_clientList == value)
return;
_clientList = value;
RaisePropertyChanged(ClientListPropertyName);
}
}
#endregion // ClientList
}
public class ClientViewModel : ViewModelBase
{
public ClientViewModel()
{
DiskList = new ObservableCollection<DiskViewModel>();
}
#region Name
public const string NamePropertyName = "Name";
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if (_name == value)
return;
_name = value;
RaisePropertyChanged(NamePropertyName);
}
}
#endregion // Name
#region DiskList
public const string DiskListPropertyName = "DiskList";
private ObservableCollection<DiskViewModel> _diskList;
public ObservableCollection<DiskViewModel> DiskList
{
get
{
return _diskList;
}
set
{
if (_diskList == value)
return;
_diskList = value;
RaisePropertyChanged(DiskListPropertyName);
}
}
#endregion // DiskList
}
public class DiskViewModel : ViewModelBase
{
public DiskViewModel()
{
}
#region Name
public const string NamePropertyName = "Name";
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if (_name == value)
return;
_name = value;
RaisePropertyChanged(NamePropertyName);
}
}
#endregion // Name
}
}
// MainWindow.xaml
<Window x:Class="WpfApplication12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:WpfApplication12.ViewModel"
xmlns:cvt="clr-namespace:InfoCore.StreamerConsole.Converters"
WindowStartupLocation="CenterScreen"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding Source={StaticResource Locator},Path=Main}">
<Grid>
<TreeView Background="AliceBlue" Margin="10"
ItemsSource="{Binding ClientList}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type vm:ClientViewModel}" ItemsSource="{Binding DiskList}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type vm:DiskViewModel}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<DataTrigger Value="true" Binding="{Binding Converter={cvt:TypeToBooleanConverter},ConverterParameter={x:Type vm:ClientViewModel}}">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Client"/>
</ContextMenu>
</Setter.Value>
</Setter>
</DataTrigger>
<!--<DataTrigger Value="true" Binding="{Binding Converter={cvt:TypeToBooleanConverter},ConverterParameter={x:Type vm:DiskViewModel}}">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Disk"/>
</ContextMenu>
</Setter.Value>
</Setter>
</DataTrigger>-->
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
</Grid>
</Window>
// ToBooleanConverter.cs
[MarkupExtensionReturnType(typeof(TypeToBooleanConverter))]
[ValueConversion(typeof(Type), typeof(bool))]
public class TypeToBooleanConverter : MarkupExtension, IValueConverter
{
private static TypeToBooleanConverter _converter = null;
public override object ProvideValue(IServiceProvider serviceProvider)
{
return _converter ?? (_converter = new TypeToBooleanConverter());
}
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (value == null)
return Binding.DoNothing;
return Type.Equals(value.GetType(), parameter);
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
return value.Equals(true) ? parameter : Binding.DoNothing;
}
}