WPF 绑定到列表框 selectedItem
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2012460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF binding to Listbox selectedItem
提问by Oli Baylis
Can anyone help with the following - been playing about with this but can't for the life of me get it to work.
任何人都可以帮助解决以下问题 - 一直在玩这个,但我一生都无法让它发挥作用。
I've got a view model which contains the following properties;
我有一个包含以下属性的视图模型;
public ObservableCollection<Rule> Rules { get; set; }
public Rule SelectedRule { get; set; }
In my XAML I've got;
在我的 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>
Now the ItemsSource works fine and I get a list of Rule objects with their names displayed in lbRules.
现在 ItemsSource 工作正常,我得到了一个 Rule 对象列表,它们的名称显示在 lbRules 中。
Trouble I am having is binding the SelectedRule property to lbRules' SelectedItem. I tried binding a textblock's text property to SelectedRule but it is always null.
我遇到的问题是将 SelectedRule 属性绑定到 lbRules 的 SelectedItem。我尝试将 textblock 的 text 属性绑定到 SelectedRule 但它始终为 null。
<TextBlock Text="{Binding Path=SelectedRule.Name}" />
The error I'm seeing in the output window is: BindingExpression path error: 'SelectedRule' property not found.
我在输出窗口中看到的错误是:BindingExpression 路径错误:找不到“SelectedRule”属性。
Can anyone help me with this binding - I can't see why it shouldn't find the SelectedRule property.
任何人都可以帮助我进行此绑定 - 我不明白为什么它不应该找到 SelectedRule 属性。
I then tried changing the textblock's text property as bellow, which works. Trouble is I want to use the SelectedRule in my ViewModel.
然后我尝试将 textblock 的 text 属性更改为波纹管,这很有效。问题是我想在我的 ViewModel 中使用 SelectedRule。
<TextBlock Text="{Binding ElementName=lbRules, Path=SelectedItem.Name}" />
Thanks very much for your help.
非常感谢您的帮助。
采纳答案by arconaut
First off, you need to implement INotifyPropertyChanged
interface in your view model and raise the PropertyChanged
event in the setter of the Rule
property. Otherwise no control that binds to the SelectedRule
property will "know" when it has been changed.
首先,您需要INotifyPropertyChanged
在视图模型中实现接口并PropertyChanged
在Rule
属性的 setter 中引发事件。否则,绑定到该SelectedRule
属性的任何控件都不会“知道”它何时被更改。
Then, your XAML
然后,您的 XAML
<TextBlock Text="{Binding Path=SelectedRule.Name}" />
is perfectly valid if this TextBlock
is outside the ListBox
's ItemTemplate
and has the same DataContext
as the ListBox
.
如果 thisTextBlock
在ListBox
's之外ItemTemplate
并且DataContext
与ListBox
.
回答by Max Galkin
Inside the DataTemplate
you're working in the context of a Rule
, that's why you cannot bind to SelectedRule.Name
-- there is no such property on a Rule
.
To bind to the original data context (which is your ViewModel) you can write:
在DataTemplate
a 的上下文中您正在工作Rule
,这就是您无法绑定到的原因SelectedRule.Name
- a 上没有这样的属性Rule
。要绑定到原始数据上下文(即您的 ViewModel),您可以编写:
<TextBlock Text="{Binding ElementName=lbRules, Path=DataContext.SelectedRule.Name}" />
UPDATE:regarding the SelectedItem property binding, it looks perfectly valid, I tried the same on my machine and it works fine. Here is my full test app:
更新:关于 SelectedItem 属性绑定,它看起来完全有效,我在我的机器上尝试了同样的方法并且它工作正常。这是我的完整测试应用程序:
XAML:
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>
Code behind:
后面的代码:
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;
}
}
}
}
回答by Arcturus
Yocoder is right,
Yocoder 是对的,
Inside the DataTemplate
, your DataContext
is set to the Rule
its currently handling..
在 中DataTemplate
,您DataContext
设置Rule
为其当前处理..
To access the parents DataContext
, you can also consider using a RelativeSource
in your binding:
要访问 parents DataContext
,您还可以考虑RelativeSource
在绑定中使用 a :
<TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ____Your Parent control here___ }}, Path=DataContext.SelectedRule.Name}" />
More info on RelativeSource
can be found here:
更多信息RelativeSource
可以在这里找到:
http://msdn.microsoft.com/en-us/library/system.windows.data.relativesource.aspx
http://msdn.microsoft.com/en-us/library/system.windows.data.relativesource.aspx
回答by Youngjae
For me, I usually use DataContext
together in order to bind two-depth property such as this question.
对我来说,我通常DataContext
一起使用以绑定两个深度属性,例如这个问题。
<TextBlock DataContext="{Binding SelectedRule}" Text="{Binding Name}" />
<TextBlock DataContext="{Binding SelectedRule}" Text="{Binding Name}" />
Or, I prefer to use ElementName
because it achieves bindings only with view controls.
或者,我更喜欢使用,ElementName
因为它仅实现与视图控件的绑定。
<TextBlock DataContext="{Binding ElementName=lbRules, Path=SelectedItem}" Text="{Binding Name}" />
<TextBlock DataContext="{Binding ElementName=lbRules, Path=SelectedItem}" Text="{Binding Name}" />
回答by ecathell
since you set your itemsource to your collection, your textbox is tied to each individual item in that collection. the selected item property is useful in this scenario if you were trying to do a master-detail form, having 2 listboxes. you would bind the second listbox's itemsource to the child collection of rules. in otherwords the selected item alerts outside controls that your source has changed, internal controls(those inside your datatemplate already are aware of the change.
由于您将 itemsource 设置为您的集合,因此您的文本框与该集合中的每个单独项目相关联。如果您尝试制作具有 2 个列表框的主从表单,则 selected item 属性在这种情况下很有用。您会将第二个列表框的 itemsource 绑定到规则的子集合。换句话说,选定的项目会在控制之外提醒您的源已更改,内部控制(数据模板内的那些已经知道更改。
and to answer your question yes in most circumstances setting the itemsource is the same as setting the datacontext of the control.
并回答您的问题是在大多数情况下设置 itemsource 与设置控件的 datacontext 相同。