【问题标题】:How to change the backgroundcolour using binding under specific conditions如何在特定条件下使用绑定更改背景颜色
【发布时间】:2011-03-11 20:42:00
【问题描述】:

如果视图模型中的特定标志为真,我需要更改数据网格的背景颜色。如果标志为假,则不要理会它。

在这种情况下是否有类似“条件绑定”的东西。

【问题讨论】:

    标签: silverlight binding


    【解决方案1】:

    您可以通过 ValueConverter 进行绑定:

    .... BackgroundColor="{Binding BooleanFlag, Converter=BoolToColorConverter}" ....
    

    MSDN 有更多信息,但您的转换器将类似于以下伪代码:

    public object Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        if (value is boolean)
        {
             return (value as boolean) ? Color.Red : Color.Blue;
        }
    }
    

    您不需要实现 ConvertBack 方法,因为它是单向绑定。

    BooleanFlag 更改时,您需要引发属性更改事件。

    【讨论】:

    • 实际问题远不止于此。如何将此绑定分配给DataGridRow 实例,以便它对每一行的每个DataContext 都敏感?
    • 它应该返回 SolidColorBrush 而不仅仅是一种颜色
    【解决方案2】:

    将布尔值转换为某种任意类型的两个实例之一的常见要求。

    我个人认为这是完成这项工作的最佳工具:Generic Bool To Value Converter(但这种观点可能存在一些偏见)

    将提供的转换器的实例放在您的用户控件的资源中:-

     <UserControl.Resources>
         <local:BoolToBrushConverter x:Key="Highlighter" FalseValue="White" TrueValue="Yellow" />
     </UserControl.Resources>
    

    现在您可以将此转换器应用于绑定,将 ViewModel 中的布尔值绑定到 Brush 类型的属性。

    但是您有一个更大的问题,您如何将此转换器应用于单个数据行? DataGrid 不允许您直接设置在每一行上设置的绑定。

    假设您不是“视图中没有代码”,您可以使用另一个静态资源来保存一个简单的Binding,然后使用数据网格LoadingRow 事件将其应用于加载的每一行.

     <UserControl.Resources>
         <local:BoolToBrushConverter x:Key="Highlighter" FalseValue="White" TrueValue="Yellow" />
         <Binding x:Key="RowBackgroundBinding" Path="yourBoolProperty" Converter="{StaticResource Highlighter}" />
     </UserControl.Resources>
    

    在数据网格上:-

     <DataGrid x:Name="dg" LoadingRow="dg_LoadingRow" ...>
    

    然后在代码隐藏中:-

        private void dg_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.SetBinding(DataGridRow.BackgroundProperty, (Binding)Resources["RowBackgroundBinding"]);
        }     
    

    这将在每行加载时设置绑定。

    【讨论】:

    • 通用布尔值转换器的链接返回 500 - 内部服务器错误。 Howerver 我能够在以下位置找到:geekswithblogs.net/codingbloke/archive/2010/05/28.aspx,它的工作原理与宣传的一样。谢谢。
    • 我不确定我们是否找到了关于这个问题的正确答案,但如果它满足查询者的需求,那就太好了。我只建议将此代码包装在操作中,例如具有 Binding 属性的 ApplyBindingToDataGridRowAction,并在 DataGrid 的 LoadingRow 上调用此操作。允许避免通过 Key 访问绑定资源。为什么我认为我们没有找到正确的答案?如上所述执行所有操作,然后更改任何项目的 ViewModel 布尔属性。此项目的行颜色不会改变...
    • @Ralph:我怀疑服务器当时有点不稳定,但链接很好。很高兴你还是找到了它。
    • @Vladimir:您是对的,该行不会更新其背景颜色。我有兴趣看到您的交互触发方法的完整实现。这将是 Xaml 的一个非常重要的部分,并且可能会遇到同样的问题。当视图模型属性更改时,上面的代码肯定会更新背景,但由于某种原因,这并没有反映在实际的 UI 中。
    • @AnthonyWJones:稍后我将添加您的解决方案的动作包装器示例,您可以确保此声明的可读性。另外我认为这个问题非常有趣,非常感谢作者,我想寻找答案“如何使该行颜色始终在 viewmodel 属性更改时更新”。我有想法尝试附加到改变背景的每一行 dataTrigger 。但是在这种情况下,我们应该描述这个触发器的原型并为每一行克隆它。稍后我会写下我的调查结果。
    【解决方案3】:

    是的,使用 IValueConverter 解决这个问题的方法是正确的,我经常使用它。 但在您的情况下,我建议仅使用 声明性方法,因为额外的转换器是您解决方案中的额外抽象,并且要理解此逻辑,其他程序员必须忽略 2 个文件:声明性和转换器实现。并且将切换的颜色在转换器中标识:(但不在声明部分中。 为避免这种情况,请使用 Blend SDK 中的 Microsoft.Expression.Interactions 和 System.Windows.Interactivity。 示例代码:

        < i:Interaction.Triggers>
            < c:DataTrigger Binding="{Binding BooleanFlagFromViewModel}" Comparison="Equal" Value="True">
                < c:ChangePropertyAction TargetName="LayoutRoot" PropertyName="Background" Value="#345678" />
            < /c:DataTrigger>
        < /i:Interaction.Triggers>
    < /Grid>
    

    希望对您有所帮助!祝你好运!

    更新

    当我在给 AnthonyWJones 的评论中写到避免通过 Key 访问绑定资源时,我建议使用 TriggerAction。

    1) 触发动作代码:

    [ContentProperty("绑定")]

    public class ApplyBindingToDataGridRowAction : TriggerAction<DataGrid>
    {
    
        protected override void Invoke(object parameter)
        {
            DataGridRowEventArgs e = (DataGridRowEventArgs) parameter;
            e.Row.SetBinding(DataGridRow.BackgroundProperty, Binding);
        }
    
        public Binding Binding { get; set; }
    }
    

    2) 在 XAML 中使用:

        < i:EventTrigger EventName="LoadingRow">
             < a:ApplyBindingToDataGridRowAction>
                  < Binding Path="Is" Converter="{StaticResource Highlighter}"/>
             < /a:ApplyBindingToDataGridRowAction>
        < /i:EventTrigger>
    < /i:Interaction.Triggers>
    

    【讨论】:

    • 我不同意额外的转换器代表“额外的抽象”(请参阅​​我的答案中的转换器)。很难看出它做了什么火箭科学,也不需要检查它的代码来确定它的意图。此外,我回应了我对 ChrisF 的评论,这不能很容易地应用于 DataGridRows。
    • 我不相信 Silverlight 版本提供 DataTriggers。当然,它不会出现在智能感知中。也许我使用了错误的命名空间? (clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions)
    • silverlight 4 中确实提供了此功能。您可以将 Microsoft.Expression.Interactions 和 System.Windows.Interactivity 程序集添加到您的项目中。在上面 xmlns:core="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions" 中描述命名空间。在 XAML 中 - “核心:”智能工作正常
    • 您需要先安装 Blend 或 Blend SDK 才能使用这些程序集,SL4 SDK 没有作为标准提供。
    【解决方案4】:

    你可以使用DataTriggers解决这个问题,当你的绑定是特定条件时改变样式。

    【讨论】:

    • @AnthonyWJones 哎呀。哪个部分在 Silverlight 中不起作用? DataTrigger 还是用一个来改变样式?
    • Silverlight 中唯一支持的触发器是 Loaded 事件触发器。
    猜你喜欢
    • 2017-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 2021-06-16
    相关资源
    最近更新 更多