【问题标题】:Make Image.Source depend on comparison of TextBox and Label values使 Image.Source 依赖于 TextBox 和 Label 值的比较
【发布时间】:2012-12-08 21:41:46
【问题描述】:

我有以下 XML:

<Items>
  <Item>
    <Name>Item One</Name>
    <MyValue>42</MyValue>
  </Item>
</Items>

和 XAML:

<DockPanel>
    <DockPanel.Resources>
        <XmlDataProvider x:Key="ItemsXml" XPath="Items/Item"
            Source="Resources/Items.xml"/>
    </DockPanel.Resources>

    <ListBox
        ItemsSource="{Binding Source={StaticResource ItemsXml}}"
        DisplayMemberPath="Name" Name="itemList"/>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.Resources>
            <Style x:Key="ValueFormat" TargetType="Label">
                <Setter Property="ContentStringFormat" Value="{}/{0,3}"/>
            </Style>
        </Grid.Resources>

        <Image Source="Icons/ConditionFalse.png" Grid.Column="0"/>

        <TextBox Name="myTextBox" VerticalAlignment="Center" Grid.Column="1"/>

        <Label
            Name="myLabel"
            DataContext="{Binding SelectedItem, ElementName=itemList}"
            Style="{StaticResource ValueFormat}"
            VerticalAlignment="Center"
            Content="{Binding XPath=MyValue}"
            Grid.Column="2"/>
    </Grid>
</DockPanel>

我想让Image.Source 依赖于TextBox.Text 等于Label* 的参考值的条件。参考值是对 XML 文件的绑定,因此使用它作为比较的基础也可以。 TextBox 将绑定到一个尚不存在的属性,因此可以作为一个选项使用。

*Label 当前使用ContentStringFormat 来更改其值。如果这是有问题的,可以摆脱它。

我可以使用a DataTrigger 直接绑定到表示此条件的属性,但这感觉像是一种黑客行为,我宁愿避免这种情况。我尝试设置一个MultiDataTrigger,如下所示,但首先我无法让Label 工作的条件(它确实适用于TextBox),其次一个常数值在我的情况下不好。当条件评估为 false 时,它​​也没有“else”子句或默认值,但如果可以首先进行检查,我希望这不会成为问题。

<Image Grid.Column="0">
    <Image.Style>
        <Style TargetType="{x:Type Image}">
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Value="/ 42"
                            Binding="{Binding Text, ElementName=myTextBox}"/>
                        <Condition Value="/ 42"
                            Binding="{Binding Content, ElementName=myLabel}"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="Source" Value="Icons/ConditionTrue.png"/>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    </Image.Style>
</Image>

【问题讨论】:

  • Converter 或 MultiValueConverter 怎么样?

标签: c# wpf xaml multidatatrigger


【解决方案1】:

除非出于技术原因,否则我建议您绑定到 ViewModel,而不是绑定到 XAML 树中的元素。使用 ViewModel,您可以将 itemList.SelectedItem 绑定到 ViewModel 上的属性(例如,将其称为 CurrentItem)。此外,将您的 Image 的 Source 绑定到另一个 ViewModel 属性(可能名为 StatusImageSource)。然后,当用户更改 itemList 中的选定值时,您可以检查 CurrentItem.Set 中标签的值是否相等,并适当地更新 StatusImageSource 值。

【讨论】:

  • 我对此表示赞同,因为这是一种很好的做法,但我不会接受它,因为存在解决问题的方法。
【解决方案2】:

Harry 的评论让我找到了正确的方向。

XAML:

<Grid.Resources>
    <local:MyImageConverter x:Key="MyImageConverter"/>
</Grid.Resources>

<Image Grid.Column="0" Grid.Row="0">
    <Image.Style>
        <Style TargetType="{x:Type Image}">
            <Setter Property="Source" Value="Icons/ConditionFalse.png"/>
            <Style.Triggers>
                <DataTrigger Value="True">
                    <DataTrigger.Binding>
                        <MultiBinding
                            Converter="{StaticResource MyImageConverter}">
                            <Binding ElementName="myTextBox" Path="Text"/>
                            <Binding ElementName="myLabel" Path="Content"/>
                        </MultiBinding>
                    </DataTrigger.Binding>
                    <Setter Property="Source" Value="Icons/ConditionTrue.png"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Image.Style>
</Image>

C#

public class MyImageConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType,
        object parameter, System.Globalization.CultureInfo culture)
    {
        System.Xml.XmlElement labelValue = values[1] as System.Xml.XmlElement;
        if (labelValue != null)
        {
            return ((string)values[0]) == labelValue.InnerText;
        }
        return false;
    }

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

这很快就会变得非常混乱。我现在正在使用它,但如果时间允许,我会按照Whyaduck 的回答将其重新加工成 ViewModel。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    相关资源
    最近更新 更多