WPF XAML数据触发器在编程方式更改属性值后无法触发 C#

3

我在我的xaml代码中有这段代码,它的作用是当我将鼠标悬停在按钮上并单击按钮时,给按钮着色。

<Border x:Class="DatasetGrid.RowHeaderButton"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300" MinWidth="30" Width="Auto">
<Border.Resources>
        <SolidColorBrush x:Key="ButtOverBrush" Color="#53C3D5" Opacity="0.2"></SolidColorBrush>
        <SolidColorBrush x:Key="ButtPressedBrush" Color="#53C3D5" Opacity="0.5"></SolidColorBrush>
</Border.Resources>
    <Border.Style>
        <Style TargetType="Border">
            <Setter Property="Background" Value="Transparent"></Setter>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="{StaticResource ButtOverBrush}"></Setter>
                </Trigger>
                <DataTrigger Binding="{Binding IsMouseDown, RelativeSource={RelativeSource Self}}" Value="True">
                    <Setter Property="Background" Value="{StaticResource ButtPressedBrush}"></Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Border.Style>
</Border>

这很好地解决了问题,但我发现一旦在代码中更改背景颜色,上述的MouseOver和MouseDown触发器就不再起作用了。

RowHeaderButton rhb = RowHeadersColumn.VisibleRowHeaders[cell.CellInfo.RowIndex];
rhb.Background = new SolidColorBrush(Color.FromArgb(100, 83, 195, 213));

我对WPF非常陌生,所以不确定出了什么问题。
编辑:
为了提供更多信息,我上面的控件是RowHeaderButton,即网格的行头。每一行在网格中都有自己的行头按钮。因此,当用户悬停或单击按钮时,它应从白色更改为上面指定的SolidColorBrush颜色。
在另一个控件DataGrid.xaml.cs的代码后台中,我有下面的代码(简化版),当选择网格中同一行的单元格时,它将更改行头的颜色。
void UpdateSelectedCells() {            

    foreach (Cell cell in VisibleColumns.SelectMany(c => c.VisibleCells))
        {
            int cellRowIndex = cell.CellInfo.RowIndex;
            cell.IsSelected = SelectedCells.Contains(cell.CellInfo);

            foreach (RowHeaderButton rhb in RowHeadersColumn.VisibleRowHeaders)
            {
                int rowHeaderIndex = Convert.ToInt16(rhb._default.Text) - 1;

                if (cellRowIndex == rowHeaderIndex)
                {
                    if (cell.IsSelected)
                    {
                        rhb.Background = new SolidColorBrush(Color.FromArgb(100, 83, 195, 213));
                    }
                    else
                    {
                        bool rowselected = false;

                        //need to check if any other cell in the row is selected, if not then color row header white
                        foreach (CellInfo celll in SelectedCells)
                        {

                            if (celll.RowIndex == cellRowIndex)
                            {
                                rowselected = true;
                                break;
                            }
                        }

                        if (rowselected == false)
                            rhb.Background = Brushes.White;
                    }
                }
            }
    }
}

我没有为此创建一个ViewModel。


1
如果您创建一个简单的ViewModel,代码将变得更好,更容易改变GUI而不直接更改GUI元素,而是更改与它们绑定的属性。 - Tony
2个回答

2
触发器正在触发,但它们的设置器被覆盖。
这是由于依赖属性值优先级。如果在代码中或XAML中作为属性设置Background属性,那么该值将覆盖任何样式设置器给出的值。一般来说,这是期望的行为:您希望能够在单个控件上覆盖样式所做的操作。
解决方案是在样式触发器中执行所有背景画刷更改。您的代码后台必须有一些原因在其进行背景画刷设置。无论是什么,找到一种使用触发器进行设置的方法。在视图模型上设置一个属性,并编写该属性的触发器。
如果您需要帮助将高级抽象转换为自己的代码,请提供足够的代码以让我了解代码后台为何设置背景以及您是否拥有视图模型。

我在主贴中添加了一些更多的信息。我没有使用视图模型,代码是针对DataGrid.xaml.cs的,而上面的XAML位于RowHeaderButton.xaml中。 - nerdalert
@nerdalert 谢谢。你分享的 Border XAML 的完整上下文是什么?那是在行标题的模板中吗? - 15ee8f99-57ff-4f92-890c-b56153
我在RowHeaderButton的代码后台中定义了一些依赖属性,也许我可以在这里创建该属性? - nerdalert
1
是的,RowHeaderButton是我自己编写的类。此外,DataGrid也是自定义编写的。无论如何,我相信我通过考虑您最初的建议创建一个新属性来确定单元格是否被选中,并根据其颜色化行来解决了这个问题。 - nerdalert
感谢您的建议和尝试理解我的代码! - nerdalert
显示剩余7条评论

1

我通过创建一个新的依赖属性并将其绑定到数据触发器来解决了这个问题。

public bool IsCellSelected
    {
        get { return (bool)GetValue(IsCellSelectedProperty); }
        set { SetValue(IsCellSelectedProperty, value); }
    }
    public static readonly DependencyProperty IsCellSelectedProperty =
        DependencyProperty.Register("IsCellSelected", typeof(bool), typeof(RowHeaderButton), new PropertyMetadata(null));

在我的XAML中,我有以下内容:
<DataTrigger Binding="{Binding IsCellSelected, RelativeSource={RelativeSource Self}}" Value="True">
     <Setter Property="Background" Value="{StaticResource ButtPressedBrush}"></Setter>
</DataTrigger>

在我的代码后台中,我使用以下代码设置值:

RowHeaderButton rhb = RowHeadersColumn.VisibleRowHeaders[cell.CellInfo.RowIndex];
rhb.IsCellSelected = true; //or false

现在我的按钮悬停和按钮点击事件没有被覆盖。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接