2010-01-06 260 views
27

任何人都可以帮助以下 - 一直在玩这个,但不能为我的生活得到它的工作。WPF绑定到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工作正常,我得到规则的列表,在lbRules显示他们的名字对象。

麻烦我正在将SelectedRule属性绑定到lbRules的SelectedItem。我尝试将文本块的文本属性绑定到SelectedRule,但它始终为空。

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

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

任何人都可以帮助我这个绑定 - 我不明白为什么它不应该找到SelectedRule属性。

然后我试着改变文本块的文本属性作为波纹管,它工作。麻烦的是我想在我的ViewModel中使用SelectedRule。

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

非常感谢您的帮助。

回答

24

首先,你需要实现INotifyPropertyChanged接口在您的视图模型,提高在Rule setter方法的PropertyChanged事件,否则没有结合到SelectedRule房产调控将“知道”时,已更改。

然后,您的XAML

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

是完全有效的,如果这是TextBlockListBoxItemTemplate并且具有相同的DataContext作为ListBox

+0

就是这样,傻了我,我没有在该视图模型上实现接口。一整天早上我的头撞在墙上! 非常感谢您的帮助。也非常感谢其他人,特别是Yacoder,花时间看看这个。 – 2010-01-06 14:27:14

+0

也谢谢我。刚刚有确切的问题。我实现了界面,但忘记提高事件。 – 2011-09-19 21:05:01

10

里面的DataTemplate你在一个Rule的环境中工作,这就是为什么你不能绑定到SelectedRule.Name - 有一个Rule没有这样的属性。 绑定到原始数​​据上下文(这是您的视图模型),你可以这样写:

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

UPDATE:关于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; 
      } 
     } 
    } 
} 
+0

谢谢你的回复。 我明白你的意思,但我不确定我是否完全理解。 问题是,DataTemplate工作正常 - 我明白模板中的上下文是规则。 这是lbRules的SelectedItem与我有问题的SelectedRule属性的绑定。 你是说通过设置ItemSource我也间接设置了列表框的DataContext? 对不起,如果我没有说清楚。我只是使用绑定到textblock来帮助我调试问题。 – 2010-01-06 11:53:05

+0

我已经更新了我的答案。 – 2010-01-06 12:06:39

+0

非常感谢您的回复。 您的回答对我来说非常有用,可以帮助我解决问题。事实证明,我的问题是我没有实施InotifyPropertyChanged,这就是为什么我将Arconaut的答复标记为答案。 谢谢你的时间。有一件事确实让我感兴趣,就是为什么你的解决方案没有实现INotifyPropertyChanged接口,但仍然可以工作... 无论如何,再次感谢您的时间。 – 2010-01-06 14:30:02

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

-6

,因为你设定itemsource到您的集合,您的文本框与该集合中的每个单独项目绑定。如果您尝试执行具有2个列表框的主 - 细节表单,则在此方案中选定的项属性很有用。你会将第二个列表框的itemsource绑定到规则的子集合。换句话说,选定的项目提醒外部控制,你的来源已经改变,内部控制(你的数据模板中的那些已经知道这个变化)

并回答你的问题是在大多数情况下设置itemsource与设置控制的DataContext的。

+3

“设置itemsource与设置控件的datacontext相同” - 请不要张贴废话:) – arconaut 2010-01-06 14:12:16

0

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

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

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

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

相关问题