36

任何人都可以提供以下帮助 - 一直在玩这个,但我一生都无法让它发挥作用。

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

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。我尝试将文本块的文本属性绑定到 SelectedRule,但它始终为空。

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

我在输出窗口中看到的错误是:BindingExpression path error: 'SelectedRule' property not found。

谁能帮我解决这个绑定 - 我不明白为什么它不应该找到 SelectedRule 属性。

然后我尝试将文本块的文本属性更改为波纹管,这有效。问题是我想在我的 ViewModel 中使用 SelectedRule。

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

非常感谢您的帮助。

4

6 回答 6

27

首先,您需要在视图模型中实现接口并在属性的设置器中INotifyPropertyChanged引发PropertyChanged事件。Rule否则,绑定到该SelectedRule属性的任何控件都不会“知道”它何时已更改。

然后,您的 XAML

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

如果这TextBlockListBox's之外ItemTemplate并且与 .s 相同DataContext,则完全有效ListBox

于 2010-01-06T14:10:37.983 回答
13

DataTemplate你在 a 的上下文中工作的内部Rule,这就是你不能绑定到的原因SelectedRule.Name——在 a 上没有这样的属性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;
            }
        }
    }
}
于 2010-01-06T11:26:27.830 回答
3

Yocoder 是对的,

在里面DataTemplate,你DataContext被设置为Rule它当前正在处理的..

要访问 parents DataContext,您还可以考虑RelativeSource在绑定中使用 a :

<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

于 2010-01-06T11:32:05.530 回答
0

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

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

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

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

于 2015-08-05T14:54:08.067 回答
0

有一个较短的版本可以绑定到选定项目的属性:

<TextBlock Text="{Binding Rules/Name}" />

于 2021-11-15T12:52:10.820 回答
-7

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

并回答你的问题是在大多数情况下设置 itemsource 与设置控件的数据上下文相同。

于 2010-01-06T12:12:30.097 回答