【问题标题】:Style DataTriggers working at design time, but not at runtime - why?样式 DataTriggers 在设计时工作,但在运行时不工作 - 为什么?
【发布时间】:2015-05-22 20:48:57
【问题描述】:

(在任何人问之前,标题是正确的:我的代码仅在 Blend 的 design 时间工作,而迄今为止最常见的是相反的:o)

在 Expression Blend 中设计 DataTemplate 时,我可以看到我的 DataTriggers 工作正常,我的示例 ViewModel 为电池电量生成一个随机值,并相应地显示边框宽度和背景颜色,无论是在BatteryLevelTemplate 本身,以及另一个面板,其中包含许多具有各自(随机)电池电量的设备,以及设计时 DataContext。

这是来自 Expression Blend 的屏幕截图:

这里是正在运行的应用程序的屏幕截图。请注意,虽然两者都使用与 DataContext 完全相同的类(但作为 Blend 中的设计时),但在运行时仅应用默认的 RedBattery 颜色设置器,即使值本身(也会影响宽度)变化:

以下是相关的代码部分:

                    <Border.Width>
                        <MultiBinding Converter="{StaticResource NormalValueConverter}" FallbackValue="10">
                            <Binding Path="NívelBateria"/>
                            <Binding Path="ActualWidth" ElementName="BatteryChargeContainer"/>
                        </MultiBinding>
                    </Border.Width>
                    <Border.Style>
                        <Style TargetType="Border">
                            <Setter Property="Background">
                                <Setter.Value>
                                    <SolidColorBrush Color="{StaticResource BatteryRed}"/>
                                </Setter.Value>
                            </Setter>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding NívelBateria, Converter={StaticResource ValorMaiorQue}, ConverterParameter=0.25}" Value="True">
                                    <Setter Property="Background">
                                        <Setter.Value>
                                            <SolidColorBrush Color="{StaticResource BatteryOrange}"/>
                                        </Setter.Value>
                                    </Setter>                                       
                                </DataTrigger>
                                <DataTrigger Binding="{Binding NívelBateria, Converter={StaticResource ValorMaiorQue}, ConverterParameter=0.5}" Value="True">
                                    <Setter Property="Background">
                                        <Setter.Value>
                                            <SolidColorBrush Color="{StaticResource BatteryYellow}"/>
                                        </Setter.Value>
                                    </Setter>                                       
                                </DataTrigger>
                                <DataTrigger Binding="{Binding NívelBateria, Converter={StaticResource ValorMaiorQue}, ConverterParameter=0.75}" Value="True">
                                    <Setter Property="Background">
                                        <Setter.Value>
                                            <SolidColorBrush Color="{StaticResource BatteryGreen}"/>
                                        </Setter.Value>
                                    </Setter>                                       
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>

============

        <DockPanel x:Name="PainelSetupsSensores" Background="#FFB8E6E8"/>
        <DockPanel x:Name="PainelSensoresDisponiveis" Background="#FFF0F0F0"
            Grid.RowSpan="2" Grid.Column="1" 
            DataContext="{Binding ReceiverAtivo}"
            d:DataContext="{d:DesignInstance Type=local:ReceiverSimulado, IsDesignTimeCreatable=True}">
            <ScrollViewer>
                <ItemsControl  ItemsSource="{Binding Sensores}" Margin="10">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <WrapPanel/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
            </ScrollViewer>
        </DockPanel>

=====================

class ValorMaiorQue : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double valor = (double)value;
        double limite = double.Parse((string)parameter);

        return valor > limite;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

更新(使用 Contango 提供的有价值的 Snoop 提示):

我“窥探”了BatteryCharge(边框)元素,发现了一件有趣的事情:

  • 受多值元素绑定影响的Width 属性工作正常,并显示在“本地”的绿色阴影行中;
  • 另一方面,不工作的Background 属性不出所料地显示为Style,并带有默认的红色值。这个不是“DataTriggered”。

我现在的疑问是我应该如何使用 Snoop(或其他任何东西)来找出未应用 DataTrigger 的原因。

【问题讨论】:

    标签: wpf datatrigger wpf-style


    【解决方案1】:

    我“偶然”发现了这个问题,下面是解释:

    1. 我安装了 Snoop、TriggerTracing 和 WPF Inspector 来检查我的 DataTriggers 应用的属性,发现 DataConverter 提供的比较总是 False;
    2. 然后我在DataConverter里面放了一个断点,发现例如ConverterParameter提供的字符串“0.75”被Double.Parsed为75.0;
    3. 然后我意识到我当前的语言是 pt-BR,小数点分隔符是逗号而不是点。然后我更改了转换器,将 InvariantCulture 参数添加到 Double.Parse。现在它可以工作了!

      double limite = double.Parse((string)parameter, CultureInfo.InvariantCulture);

    【讨论】:

      【解决方案2】:

      您的运行时 DataContext 设置不正确,因此您的代码无法在运行时绑定到正确的属性。

      请注意,运行时 DataContext 与设计时 DataContext 完全分离,并使用不同的 XAML 来设置运行时 DataContext。

      我建议使用 Snoop 来解决问题,您可以使用它来标记由于运行时 DataContext 错误而导致的绑定错误,请在此处查看我的答案:

      ReSharper WPF error: "Cannot resolve symbol "MyVariable" due to unknown DataContext"

      【讨论】:

      • 那么,为什么其他所有属性都设置正确?在 datafgrid、样式、模板的默认设置器中设置的非常默认的红色背景正在工作。也就是说,datacontext 工作正常,datatemplate 工作正常,样式工作正常,setter 工作正常,只有 数据触发器 显然不工作......
      • 好点。通常,像这样的事情可以追溯到某个地方的错误 DataContext。您能否运行 Snoop 并检查所有 DataContext 在运行时是否设置正确?请参阅我的答案中的最后一个链接。
      • 不幸的是,我没有 ReSharper 或 Snoop。明天我打算做一些逐步测试,看看我是否能找出问题所在,谢谢。
      • Snoop 是免费的!谷歌“wpf snoop”
      • 是的,Snoop 是 WPF 的一个了不起的工具,如果打开过滤器,它将在运行时自动发现任何错误的 DataBinding,请参阅我的答案中引用的 URL。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-08
      • 1970-01-01
      • 2019-05-07
      • 2011-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多