上下文菜单的 RelativeSource 停止 DataTrigger 工作
RelativeSource For Context Menu stops DataTrigger working
第一次 post 很久 reader 并且是 wpf 的新手所以请对我温柔点:-)
我正在尝试使用 ListView 创建用户列表,我在 CollectionView 中分组,离线用户为红色。使用仅在单击用户名时显示的上下文菜单。
上下文菜单的代码我从另一个 post 这里 ContextMenu for ListViewItem only
我的问题是,一旦我添加上下文菜单,颜色变化就不再触发,
所以我相信我在不了解它们是如何工作的情况下混合使用这些方法。
<Grid>
<ListView x:Name="lvUsers" ItemsSource="{Binding items}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Icon}"/>
<TextBlock Margin="10,0,0,0" Text="{Binding UserName}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<ListView.Resources>
<ContextMenu x:Key="ItemContextMenu">
<MenuItem Header="More Info" Click="MenuItemDelete_Click" Command="{Binding Path=DataContext.MoreInfo, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" Background="WhiteSmoke" />
</ContextMenu>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Foreground" Value = "Red"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value ="Online">
<Setter Property="Foreground" Value="Black" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}" >
<Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}" />
</Style>
</ListView.ItemContainerStyle>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" FontSize="14" Foreground="Black" HorizontalAlignment="Center" Text="{Binding Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
[它应该是什么样子][1]
![1]: https://i.stack.imgur.com/yu0Rx.png
{
InitializeComponent();
List<User> items = new List<User>();
items.Add(new User() { Icon = ".\images\white.png", UserName = "Tim Black", MessageColor ="Black", Status = Status.Online });
items.Add(new User() { Icon = ".\white.png", UserName = "Colin Black", MessageColor = "Black", Status = Status.Online });
items.Add(new User() { Icon = ".\images\white.png", UserName = "Fred in Red", MessageColor = "Red" , Status = Status.Offline });
lvUsers.ItemsSource = items;
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lvUsers.ItemsSource);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("Status");
view.GroupDescriptions.Add(groupDescription);
}
private void MenuItemDelete_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("context Pressed as source" + e.Source.ToString());
}
}
public enum Status { Online, Offline };
public class User
{
public string Icon { get; set; }
public string UserName { get; set; }
public string MessageColor { get; set; }
public Status Status { get; set; }
}
我成功了。
向您的项目添加一个新的 class StatusToForeGroundConverter
。
public class StatusToForeGroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is Status status)
{
return status == Status.Online ? "black" : "red";
}
//fallback
return "black";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
将转换器添加到您的 XAML:
<Window.Resources>
<local:StatusToForeGroundConverter x:Key="StatusConverter"/>
</Window.Resources>
然后像这样绑定它:
<TextBlock Margin="10,0,0,0" Text="{Binding UserName}" Foreground="{Binding Status,Converter={StaticResource StatusConverter}}"/>
完整 xaml:
<Grid>
<ListView x:Name="lvUsers" ItemsSource="{Binding items}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Icon}"/>
<TextBlock Margin="10,0,0,0" Text="{Binding UserName}" Foreground="{Binding Status,Converter={StaticResource StatusConverter}}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<ListView.Resources>
<ContextMenu x:Key="ItemContextMenu">
<MenuItem Header="More Info" Click="MenuItemDelete_Click" Command="{Binding Path=DataContext.MoreInfo, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" Background="WhiteSmoke" />
</ContextMenu>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}" >
<Setter Property="Foreground" Value="{Binding MessageColor}" />
</Style>
</ListView.ItemContainerStyle>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" FontSize="14" Foreground="Black" HorizontalAlignment="Center" Text="{Binding Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
第一次 post 很久 reader 并且是 wpf 的新手所以请对我温柔点:-)
我正在尝试使用 ListView 创建用户列表,我在 CollectionView 中分组,离线用户为红色。使用仅在单击用户名时显示的上下文菜单。
上下文菜单的代码我从另一个 post 这里 ContextMenu for ListViewItem only
我的问题是,一旦我添加上下文菜单,颜色变化就不再触发, 所以我相信我在不了解它们是如何工作的情况下混合使用这些方法。
<Grid>
<ListView x:Name="lvUsers" ItemsSource="{Binding items}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Icon}"/>
<TextBlock Margin="10,0,0,0" Text="{Binding UserName}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<ListView.Resources>
<ContextMenu x:Key="ItemContextMenu">
<MenuItem Header="More Info" Click="MenuItemDelete_Click" Command="{Binding Path=DataContext.MoreInfo, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" Background="WhiteSmoke" />
</ContextMenu>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Foreground" Value = "Red"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value ="Online">
<Setter Property="Foreground" Value="Black" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}" >
<Setter Property="ContextMenu" Value="{StaticResource ItemContextMenu}" />
</Style>
</ListView.ItemContainerStyle>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" FontSize="14" Foreground="Black" HorizontalAlignment="Center" Text="{Binding Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
[它应该是什么样子][1]
![1]: https://i.stack.imgur.com/yu0Rx.png
{
InitializeComponent();
List<User> items = new List<User>();
items.Add(new User() { Icon = ".\images\white.png", UserName = "Tim Black", MessageColor ="Black", Status = Status.Online });
items.Add(new User() { Icon = ".\white.png", UserName = "Colin Black", MessageColor = "Black", Status = Status.Online });
items.Add(new User() { Icon = ".\images\white.png", UserName = "Fred in Red", MessageColor = "Red" , Status = Status.Offline });
lvUsers.ItemsSource = items;
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lvUsers.ItemsSource);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("Status");
view.GroupDescriptions.Add(groupDescription);
}
private void MenuItemDelete_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("context Pressed as source" + e.Source.ToString());
}
}
public enum Status { Online, Offline };
public class User
{
public string Icon { get; set; }
public string UserName { get; set; }
public string MessageColor { get; set; }
public Status Status { get; set; }
}
我成功了。
向您的项目添加一个新的 class StatusToForeGroundConverter
。
public class StatusToForeGroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is Status status)
{
return status == Status.Online ? "black" : "red";
}
//fallback
return "black";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
将转换器添加到您的 XAML:
<Window.Resources>
<local:StatusToForeGroundConverter x:Key="StatusConverter"/>
</Window.Resources>
然后像这样绑定它:
<TextBlock Margin="10,0,0,0" Text="{Binding UserName}" Foreground="{Binding Status,Converter={StaticResource StatusConverter}}"/>
完整 xaml:
<Grid>
<ListView x:Name="lvUsers" ItemsSource="{Binding items}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Icon}"/>
<TextBlock Margin="10,0,0,0" Text="{Binding UserName}" Foreground="{Binding Status,Converter={StaticResource StatusConverter}}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<ListView.Resources>
<ContextMenu x:Key="ItemContextMenu">
<MenuItem Header="More Info" Click="MenuItemDelete_Click" Command="{Binding Path=DataContext.MoreInfo, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}" Background="WhiteSmoke" />
</ContextMenu>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}" >
<Setter Property="Foreground" Value="{Binding MessageColor}" />
</Style>
</ListView.ItemContainerStyle>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" FontSize="14" Foreground="Black" HorizontalAlignment="Center" Text="{Binding Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>