上下文菜单的 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>