web-dev-qa-db-ja.com

Listbox selectedItemへのWPFバインディング

誰でも次のことを手伝うことができますか?.

次のプロパティを含むビューモデルがあります。

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に名前が表示されたRuleオブジェクトのリストを取得します。

私が抱えている問題は、SelectedRuleプロパティをlbRulesのSelectedItemにバインドしていることです。テキストブロックのテキストプロパティをSelectedRuleにバインドしようとしましたが、常にnullです。

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

出力ウィンドウに表示されるエラー:BindingExpression path error: 'SelectedRule' property not found。

誰もこのバインディングで私を助けることができます-SelectedRuleプロパティが見つからない理由がわかりません。

次に、テキストブロックのテキストプロパティを以下のように変更してみました。問題は、ViewModelでSelectedRuleを使用することです。

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

ご協力ありがとうございます。

30
Oli Baylis

まず、ビューモデルにINotifyPropertyChangedインターフェイスを実装し、PropertyChangedプロパティのセッターでRuleイベントを発生させる必要があります。そうでない場合、SelectedRuleプロパティにバインドするコントロールは、変更されたときに「認識」しません。

次に、XAML

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

このTextBlockListBoxItemTemplateの外にあり、DataContextと同じListBoxを持つ場合、完全に有効です。

25
arconaut

DataTemplate内では、Ruleのコンテキストで作業しているため、SelectedRule.Nameにバインドすることはできません。このようなプロパティはRuleにありません。元のデータコンテキスト(ViewModel)にバインドするには、次のように記述できます。

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

PDATE: 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;
            }
        }
    }
}
11
Max Galkin

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
Arcturus

私にとっては、この質問のような2階層のプロパティをバインドするために、通常DataContextを一緒に使用します。

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

または、ビューコントロールでのみバインディングを実現するため、ElementNameを使用することを好みます。

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

0
Youngjae