この単純なデータバインディングのシナリオが機能しないのはなぜですか? (コンボボックス関連)
-
19-08-2019 - |
質問
私はしばらくこの問題に頭を悩ませてきましたが、今は困惑しています。
問題のシナリオはコードとして説明する方が簡単なので、うまくいけばそれ自体が語られることを願っています。まず、XAMLに以下を含むsilverlightアプリケーションがあります...
<UserControl x:Class="SilverlightApplication2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<UserControl.Resources>
<DataTemplate x:Key="icTemplate">
<ComboBox ItemsSource="{Binding StringsChild}" SelectedItem="{Binding SelectedItem}"/>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<ItemsControl x:Name="ic" ItemTemplate="{StaticResource icTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Button Click="Save" Grid.Row="1" Content="GO"/>
</Grid>
コードビハインドは次のようになります...(すべて単一のクラスファイルに記述されているため、自分のプロジェクトにコピーしてコンパイルしやすくなります)
namespace SilverlightApplication2
{
public partial class Page : UserControl
{
public ObservableCollection<SomeClass> StringsParent { get; set; }
public Page()
{
InitializeComponent();
StringsParent = new ObservableCollection<SomeClass>();
ic.ItemsSource = StringsParent;
}
private void Save(object sender, RoutedEventArgs e)
{
SomeClass c = new SomeClass();
c.StringsChild.Add("First");
c.StringsChild.Add("Second");
c.StringsChild.SetSelectedItem("Second");
StringsParent.Add(c);
}
}
public class SomeClass
{
public SelectableObservablecollection<string> StringsChild { get; set; }
public SomeClass()
{
StringsChild = new SelectableObservablecollection<string>();
}
}
public class SelectableObservablecollection<T> : ObservableCollection<T>
{
public SelectableObservablecollection()
: base()
{
}
public void SetSelectedItem<Q>(Q selectedItem)
{
foreach (T item in this)
{
if (item.Equals(selectedItem))
{
SelectedItem = item;
return;
}
}
}
private T _selectedItem;
public T SelectedItem
{
get
{
return _selectedItem;
}
set
{
_selectedItem = value;
OnPropertyChanged(new PropertyChangedEventArgs("SelectedItem"));
}
}
}
}
では、説明しましょう... たとえば、コレクションをComboBoxにバインドするときにComboBoxの SelectedItem をバインドできるように、 SelectedItem プロパティを持つObservableCollectionを作成する一般的な方法を記述しようとしました。 strong>プロパティ。
ただし、何らかの理由で、ComboBoxがItemTemplateを介して効果的にネストされている場合は機能しないようです。リストのリスト、つまり、何が間違っているのか分からなくなるほど単純なシナリオが事実上あります。
コードを実行すると、テンプレート化されたComboBoxは正しいアイテムを取得しますが、バインディングにもかかわらずSelectedItemに設定されることはありません。
かなり長くかかっていることは知っていますが、...何かアイデアはありますか?
たくさんありがとう
解決
デバッガーの出力は、実際に問題のヒントを提供します:
System.Windows.Dataエラー:BindingExpressionパスエラー:「ExpressedElements.SomeClass」で「SelectedItem」プロパティが見つかりません「ExpressionElements.SomeClass」(HashCode = 49044892)。 BindingExpression:Path = 'SelectedItem' DataItem = 'ExpressionElements.SomeClass'(HashCode = 49044892);ターゲット要素は 'System.Windows.Controls.ComboBox'(Name = '');ターゲットプロパティは 'SelectedItem'(タイプ 'System.Object')です。
テンプレートのデータコンテキストはSomeClassクラスのインスタンスであるため、SelectedItemバインディングをSelectedItemから StringsChild.SelectedItem に変更するだけです:
<DataTemplate x:Key="icTemplate">
<ComboBox ItemsSource="{Binding StringsChild}"
SelectedItem="{Binding StringsChild.SelectedItem}"/>
</DataTemplate>