【问题标题】:Bind TextBlock.Text to specific item-property in collection where value matches another binding将 TextBlock.Text 绑定到集合中的特定项目属性,其中值与另一个绑定匹配
【发布时间】:2017-10-19 14:51:32
【问题描述】:


试图留在 MVVM 道路上,我一直在为以下任务苦苦挣扎几个小时:

我想显示特定项目的字符串值(在 TextBlock 中),它是 UserCollection (ObservableCollection<Tuple<int, string>>) 的一部分。选择应通过集合中项目的 Int 属性进行,与 MyOrder 中绑定的 IdCreatedByUser-Property 匹配。

为了让事情更清楚:

一个包含 ID (int) 和 NAME (string) 的 UserCollection:

public ObservableCollection<Tuple<int, string>> UserCollection;

一个 MyOrder-Property 持有 Orders-Class 的一个实例:

public Order MyOrder;

这里是 Orders 类的示例。

public class Order: INotifyPropertyChanged
{
  public string Comment;
  public int IdCreatedByUser;
  public bool IsComplete;
}

请注意,这只是属性的一个示例。知道这里缺少 get、set 。

我想出的唯一解决方案是像这样劫持 Combox:

<ComboBox ItemsSource="{Binding UserCollection}"
    DisplayMemberPath="Item2"
    SelectedValue="{Binding MyOrder.IdCreatedByUser}"
    SelectedValuePath="Item1">

    <ComboBox.Template>
        <ControlTemplate>
            <TextBlock Text="{Binding SelectedItem.Item2,RelativeSource={RelativeSource Mode=TemplatedParent}}" />
        </ControlTemplate>
    </ComboBox.Template>
</ComboBox>

我可以使用 ItemsSource、SelectedValue 和 SelectedValuePath 的事实使我能够选择和显示所需的项目。任何使用 TextBlocks 的解决方案? 我也在考虑一个转换器或额外的属性..但也许你可以告诉我一种以更好的方式设计它的方法.. 谢谢!

【问题讨论】:

  • 在网络浏览器中,尖括号用来表示标签。因此,如果您没有在 ObservableCollection&lt;Tuple&lt;int, string&gt;&gt; 周围加上反引号以通知该降价它将按字面意思显示,它会显示为“ObservableCollection>”,这不是您想要的。
  • 也就是说,您的问题解决方案很好。我昨天在生产代码中做了同样的事情。您可以改为write a MultiConverter 并将其与多重绑定一起使用,但它不会那么冗长。您可以在绑定中索引集合,但只能使用文字索引值:{Binding MyColl[1].Foo} 等。
  • 另一个选项是给你的视图模型一个SelectedUser属性,当MyOrderMyOrder.IdCreatedByUser改变时返回UserCollection[MyOrder.IdCreatedByUser]并引发PropertyChanged("SelectedUser")
  • 这也是一个不错的方法。这里的问题是我有更多的控件来向我显示特定用户的名称..比如 Orders-Class 中的属性 IdFinishedByUser、IdEditedByUser 等等。所以我必须在我的 Viewmodel 中处理更多属性,我想防止这种情况发生。我的 ComboBox 劫持是否有任何关于 TextBlocks 的正常使用的问题?
  • 我认为它不会有任何问题。我会考虑的一件事是编写一个 ComboBox 样式来简化 XAML,如果你正在做一堆这样的事情。我会把昨天做的删掉然后贴出来。

标签: wpf xaml


【解决方案1】:

这实质上使您的专用 ComboBox 易于重复使用。像FontWeight 这样的东西将被ContentPresenter 继承。

<Style x:Key="CollectionLookupComboBox" TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}">
    <!-- 
    Default to readonly, but you can override that for particular instances 
    if that's useful somewhere. 
    -->
    <Setter Property="IsReadOnly" Value="True" />
    <Style.Triggers>
        <Trigger Property="IsReadOnly" Value="True">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ComboBox">
                        <Grid>
                            <Border
                                x:Name="OuterBorder"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                BorderBrush="Transparent"
                                HorizontalAlignment="Stretch"
                                VerticalAlignment="Stretch"
                                Background="Transparent"
                                >
                                <!-- 
                                The margin here keeps the text in the same spot when I toggle IsReadOnly,
                                with the default theme I have. May need to fiddle with that to get it to 
                                look right for you. 
                                -->
                                <ContentPresenter 
                                    Margin="3,2,2,0"
                                    IsHitTestVisible="False"
                                    Content="{TemplateBinding SelectionBoxItem}"
                                    ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
                                    ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                                    VerticalAlignment="Stretch"
                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                    />
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Trigger>
    </Style.Triggers>
</Style>

例子——这太过分了;您不需要 ItemTemplate 或粗体字,但它演示了如何支持所有常见的 ComboBox 内容:

<StackPanel 
    Orientation="Vertical"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    >
    <CheckBox
        x:Name="ReadOnlyCheckBox"
        IsChecked="True"
        Margin="1"
        Content="Read-Only" 
        />
    <ComboBox
        Margin="1"
        Style="{StaticResource CollectionLookupComboBox}"
        IsReadOnly="{Binding IsChecked, ElementName=ReadOnlyCheckBox}"
        MinWidth="80"
        SelectedIndex="0"
        FontWeight="Bold"
        Foreground="Green"
        >
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <Border BorderBrush="DeepSkyBlue" BorderThickness="2" CornerRadius="4">
                    <Label Content="{Binding}" />
                </Border>
            </DataTemplate>
        </ComboBox.ItemTemplate>
        <sys:String>First Item</sys:String>
        <sys:String>Second Item</sys:String>
    </ComboBox>
</StackPanel>

【讨论】:

    猜你喜欢
    • 2018-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 2010-11-14
    相关资源
    最近更新 更多