WPF绑定到Listbox selectedItem

时间:2010-01-06 11:13:22

标签: wpf binding listbox selecteditem

任何人都可以帮助以下内容 - 一直在玩这个,但不能让我的生活让它发挥作用。

我有一个包含以下属性的视图模型;

public ObservableCollection<Rule> Rules { get; set; }
public Rule SelectedRule { get; set; }

在我的XAML中我有;

<ListBox x:Name="lbRules" ItemsSource="{Binding Path=Rules}" 
         SelectedItem="{Binding Path=SelectedRule, Mode=TwoWay}">
<ListBox.ItemTemplate>
    <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Name:" />
                <TextBox x:Name="ruleName">
                    <TextBox.Text>
                        <Binding Path="Name" UpdateSourceTrigger="PropertyChanged" />
                    </TextBox.Text>
                </TextBox>
            </StackPanel>
    </DataTemplate>
</ListBox.ItemTemplate>

现在ItemsSource工作正常,我得到一个Rule对象列表,其名称显示在lbRules中。

我遇到的麻烦是将SelectedRule属性绑定到lbRules的SelectedItem。我尝试将textblock的text属性绑定到SelectedRule,但它始终为null。

<TextBlock Text="{Binding Path=SelectedRule.Name}" />

我在输出窗口中看到的错误是: BindingExpression路径错误:找不到'SelectedRule'属性。

任何人都可以帮我解决这个问题 - 我不明白为什么它不应该找到SelectedRule属性。

然后我尝试将textblock的text属性更改为bellow,这有效。麻烦的是我想在我的ViewModel中使用SelectedRule。

<TextBlock Text="{Binding ElementName=lbRules, Path=SelectedItem.Name}" />

非常感谢你的帮助。

5 个答案:

答案 0 :(得分:25)

首先,您需要在视图模型中实现INotifyPropertyChanged接口,并在PropertyChanged属性的setter中引发Rule事件。否则,绑定到SelectedRule属性的控件将“知道”何时更改。

然后,你的XAML

<TextBlock Text="{Binding Path=SelectedRule.Name}" />
如果此TextBlock超出ListBox的{​​{1}}并且ItemTemplateDataContext相同,则

完全有效。

答案 1 :(得分:11)

在你DataTemplate的上下文Rule内,这就是你无法绑定SelectedRule.Name的原因 - Rule上没有这样的属性。 要绑定到原始数​​据上下文(这是您的ViewModel),您可以编写:

<TextBlock Text="{Binding ElementName=lbRules, Path=DataContext.SelectedRule.Name}" />
关于SelectedItem属性绑定的

更新:,它看起来完全有效,我在我的机器上尝试了同样的工作,它工作正常。这是我的完整测试应用程序:

XAML:

<Window x:Class="TestWpfApplication.ListBoxSelectedItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ListBoxSelectedItem" Height="300" Width="300"
    xmlns:app="clr-namespace:TestWpfApplication">
    <Window.DataContext>
        <app:ListBoxSelectedItemViewModel/>
    </Window.DataContext>
    <ListBox ItemsSource="{Binding Path=Rules}" SelectedItem="{Binding Path=SelectedRule, Mode=TwoWay}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Name:" />
                    <TextBox Text="{Binding Name}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Window>

代码背后:

namespace TestWpfApplication
{
    /// <summary>
    /// Interaction logic for ListBoxSelectedItem.xaml
    /// </summary>
    public partial class ListBoxSelectedItem : Window
    {
        public ListBoxSelectedItem()
        {
            InitializeComponent();
        }
    }


    public class Rule
    {
        public string Name { get; set; }
    }

    public class ListBoxSelectedItemViewModel
    {
        public ListBoxSelectedItemViewModel()
        {
            Rules = new ObservableCollection<Rule>()
            {
                new Rule() { Name = "Rule 1"},
                new Rule() { Name = "Rule 2"},
                new Rule() { Name = "Rule 3"},
            };
        }

        public ObservableCollection<Rule> Rules { get; private set; }

        private Rule selectedRule;
        public Rule SelectedRule
        {
            get { return selectedRule; }
            set
            {
                selectedRule = value;
            }
        }
    }
}

答案 2 :(得分:3)

Yocoder是对的,

DataTemplate内,您的DataContext设置为其当前处理的Rule ..

要访问父母DataContext,您还可以考虑在绑定中使用RelativeSource

<TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ____Your Parent control here___ }}, Path=DataContext.SelectedRule.Name}" />

RelativeSource的更多信息可在此处找到:

http://msdn.microsoft.com/en-us/library/system.windows.data.relativesource.aspx

答案 3 :(得分:0)

对我来说,我通常一起使用DataContext来绑定两个深度属性,例如这个问题。

<TextBlock DataContext="{Binding SelectedRule}" Text="{Binding Name}" />

或者,我更喜欢使用ElementName,因为它只能使用视图控件实现绑定。

<TextBlock DataContext="{Binding ElementName=lbRules, Path=SelectedItem}" Text="{Binding Name}" />

答案 4 :(得分:-7)

因为您将itemsource设置为您的集合,所以您的文本框与该集合中的每个单独项目相关联。如果您尝试执行具有2个列表框的主 - 详细信息表单,则所选项属性在此方案中很有用。您可以将第二个列表框的itemsource绑定到子规则集合。换句话说,所选项目会警告您的源已更改的外部控件,内部控件(数据模板中的那些已经知道更改。

并在大多数情况下回答您的问题是设置itemsource与设置控件的datacontext相同。