誰でも次のことを手伝うことができますか?.
次のプロパティを含むビューモデルがあります。
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}" />
ご協力ありがとうございます。
まず、ビューモデルにINotifyPropertyChanged
インターフェイスを実装し、PropertyChanged
プロパティのセッターでRule
イベントを発生させる必要があります。そうでない場合、SelectedRule
プロパティにバインドするコントロールは、変更されたときに「認識」しません。
次に、XAML
<TextBlock Text="{Binding Path=SelectedRule.Name}" />
このTextBlock
がListBox
のItemTemplate
の外にあり、DataContext
と同じListBox
を持つ場合、完全に有効です。
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;
}
}
}
}
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
私にとっては、この質問のような2階層のプロパティをバインドするために、通常DataContext
を一緒に使用します。
<TextBlock DataContext="{Binding SelectedRule}" Text="{Binding Name}" />
または、ビューコントロールでのみバインディングを実現するため、ElementName
を使用することを好みます。
<TextBlock DataContext="{Binding ElementName=lbRules, Path=SelectedItem}" Text="{Binding Name}" />