简体   繁体   English

将TextBlock的文本绑定到ListBox的SeletedItem文本吗?

[英]Bind TextBlock's Text to the SeletedItem text of a ListBox?

I have a ListBox that I provide with DisplayMemberPath in run time, and have a TextBlock that I want its Text property to be bound to the selected item text of the ListBox, hardcoding the value works: 我有一个在运行时随DisplayMemberPath一起提供的ListBox,并且有一个TextBlock ,我希望将其Text属性绑定到ListBox的选定项目文本,对值进行硬编码:

<TextBlock Text="{Binding ElementName=lstBx, Path=SelectedItem.Title}"/>

But how I do it without knowing which property is used for displaying? 但是,如何在不知道用于显示的属性的情况下如何做呢?

Edit 编辑

The ListBox and the TextBlock are parts of the ControlTemplate of a custom control that has a custom DisplayMemberPath property that I bind to the listBox's DisplayMemberPath ListBoxTextBlock是自定义控件的ControlTemplate的一部分,该ControlTemplate具有自定义DisplayMemberPath属性,该属性已绑定到listBox的DisplayMemberPath

    <ListBox Name="lstBx" ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ItemsSource}" 
DisplayMemberPath="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DisplayMemberPath}" 
SelectedValuePath="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedValuePath}"/>

In my opinion you have 2 options: 我认为您有2种选择:

  1. create your own extension of Listbox. 创建您自己的Listbox扩展名。 which has a kind of SelectedDisplay property (it should work like SelectedValue property, but using DisplayMemberPath instead of SelectedValuePath ) 它具有一种SelectedDisplay属性(应类似于SelectedValue属性,但使用DisplayMemberPath而不是SelectedValuePath
  2. use a MultiBinding and some lamba expression dynimic building. 使用MultiBinding和一些lamba表达式动态构建。

I will show you the second solution. 我将向您展示第二种解决方案。 First of all the multibinding: 首先是多重绑定:

<TextBlock>
    <TextBlock.Text>
        <MultiBinding Mode="OneWay" Converter="{StaticResource PropertyMultiValueConverter}">
            <Binding ElementName="lstBx" Path="SelectedItem"/>
            <Binding ElementName="lstBx" Path="DisplayMemberPath" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

Now the code for the PropertyMultiValueConverter class (of course it can be improved and optimized for avoiding a continuos lambda expression generation): 现在, PropertyMultiValueConverter类的代码(当然可以进行改进和优化,以避免生成连续的lambda表达式):

public class PropertyMultiValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        object selectedItem = values[0];
        string displayMemberPath = values[1] as string;

        if (selectedItem != null)
        {
            ParameterExpression param =
                System.Linq.Expressions.Expression.Parameter(selectedItem.GetType(), "x");
            MemberExpression body =
                System.Linq.Expressions.Expression.Property(param, displayMemberPath);

            LambdaExpression lambda =
                System.Linq.Expressions.Expression.Lambda(body, param);

            Delegate expression = lambda.Compile();
            return expression.DynamicInvoke(selectedItem);
        }
        else
        {
            return null;
        }
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Lambda expressions are faster than using reflection, so I prefer this way. Lambda表达式比使用反射更快,因此我更喜欢这种方式。 As you can see the generated lambda expression retrieves the value of the property and returns it. 如您所见,生成的lambda表达式检索属性的值并返回它。

I think i get your question. 我想我得到你的问题。 Seems you meant SelectedItem.{CanBeAnyProperty} right? 看来您的意思是SelectedItem。{CanBeAnyProperty}对吗?

One solution could be you bind your textblock like below : 一种解决方案是像下面这样绑定文本块:

<TextBlock Text="{Binding ElementName=lstBx, Path=SelectedItem}"/>

And override SelectedItem ToString() method to return appropriate desired property value. 并重写SelectedItem ToString()方法以返回适当的所需属性值。

For example: say your Item bound to list is Person. 例如:说您绑定到列表的项目是Person。

So you can override ToString() method of person class like : 因此,您可以覆盖人员类的ToString()方法,例如:

class Person{

Public string ToString(){
return Name; /*this again you need to work out runtime* OR/
return Age.ToString();}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM