样式DataTriggers在设计时工作,但不是在运行时 - 为什么?

时间:2015-05-22 20:48:57

标签: wpf datatrigger wpf-style

(在任何人问之前,标题是正确的:我的代码只在Blend中的设计时间工作,而到目前为止最常见的是相反的:o)

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

以下是Expression Blend的截图:

enter image description here

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

enter image description here

以下是相关的代码部分:

                    <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”。

enter image description here

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

2 个答案:

答案 0 :(得分:1)

我意外地发现了这个问题,这里有解释:

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

      

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

答案 1 :(得分:0)

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

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

我建议使用Snoop来解决问题,你可以使用它来标记由于运行时DataContext错误导致的绑定错误,请参阅我的回答:

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