将TextBlock.Text绑定到集合中的特定item-property,其中value与另一个绑定匹配

时间:2017-10-19 14:51:32

标签: wpf xaml


为了保持MVVM之路,我几个小时都在努力完成以下任务:

我想显示特定Item的String-value(在TextBlock中),它是UserCollection(ObservableCollection<Tuple<int, string>>)的一部分。选择应通过Collection中项目的Int-property进行,匹配MyOrder中绑定的IdCreatedByUser-Property。

为了使事情更清楚:

包含ID(int)和NAME(字符串)的UserCollection:

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

持有订单类实例的MyOrder-Property:

public Order MyOrder;

这是Orders-class的一个例子。

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的任何解决方案? 我也在考虑转换器或额外的属性..但也许你可以告诉我一种方法来更好地设计它。 谢谢!

1 个答案:

答案 0 :(得分:0)

这实际上使您的专用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东西:

enter image description here enter image description here

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