wpf - two - ComboBox ItemTemplateはドロップダウンでしか動作しません



wpf combobox foreach (2)

ItemsSourceがControlsのコレクションであるComboBoxを表示しようとしています(これはPropertyGridの一部であり、ComboBoxはコントロールの名前を表示する必要があり、ユーザーはコントロールの1つを選択できる必要があります)。 ここでは、問題の非常に単純化された再現があります:

<ComboBox ItemsSource="{Binding GroupBoxes}" SelectedValue="{Binding SelectedGroupBox}">
  <ComboBox.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding Name}"/>
    </DataTemplate>
  </ComboBox.ItemTemplate>          
</ComboBox>

GroupBoxesおよびSelectedGroupBoxは、ObservableCollectionおよびGroupBox型のDependencyPropertiesです。

バインディングが機能する - コントロール名がComboBox-DropDownに表示され、別のアイテムを選択すると、SelectedGroupBoxプロパティが正しく更新されていることがわかります。 問題:選択したアイテムがコンボボックスに表示されることはありません。 コードからSelectedGroupBoxプロパティを設定することも期待どおりに機能します。ComboBoxはSelectionChangedを発生させ、SelectedValueは正しいですが、それでも現在の値は表示されません。

他のクラスのクラスと全く同じことを行うと、すべてが期待通りに機能します。

回答を探す私は同じような問題を抱えている人からの多くの投稿に出くわしましたが、ほとんどすべてがBinding proplemsでしたが、ここではそうではありません。

編集:

試してみることを簡単にするために、ここにコードがあります。 上記のXAMLを新しいウィンドウにドロップし、コードを以下のコードの中にドロップします。

public MainWindow() {
    InitializeComponent();
    this.DataContext = this;
    this.GroupBoxes = new ObservableCollection<GroupBox>();
    this.GroupBoxes.Add(new GroupBox() { Name = "AAA", Header = "AAA", Height = 100, Background = Brushes.Purple });
    this.GroupBoxes.Add(new GroupBox() { Name = "BBB", Header = "BBB", Height = 100, Background = Brushes.Purple });
    this.GroupBoxes.Add(new GroupBox() { Name = "CCC", Header = "CCC", Height = 100, Background = Brushes.Purple });
    this.GroupBoxes.Add(new GroupBox() { Name = "DDD", Header = "DDD", Height = 100, Background = Brushes.Purple });
    this.GroupBoxes.Add(new GroupBox() { Name = "EEE", Header = "EEE", Height = 100, Background = Brushes.Purple });
}

#region GroupBoxesProperty

public static readonly DependencyProperty GroupBoxesProperty = DependencyProperty.Register(
    "GroupBoxes", typeof(ObservableCollection<GroupBox>), typeof(MainWindow)
);

public ObservableCollection<GroupBox> GroupBoxes {
    get { return (ObservableCollection<GroupBox>)GetValue(GroupBoxesProperty); }
    set { SetValue(GroupBoxesProperty, value); }
}

#endregion

#region SelectedGroupBoxProperty

public static readonly DependencyProperty SelectedGroupBoxProperty = DependencyProperty.Register(
    "SelectedGroupBox", typeof(GroupBox), typeof(MainWindow),
    new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (s, e) => (s as MainWindow).OnSelectedGroupBoxChanged())
);

public GroupBox SelectedGroupBox {
    get { return (GroupBox)GetValue(SelectedGroupBoxProperty); }
    set { SetValue(SelectedGroupBoxProperty, value); }
}

void OnSelectedGroupBoxChanged() {
    Console.WriteLine("selection is now " + this.SelectedGroupBox.Name);
}

#endregion

https://src-bin.com


Answer #1

非常に複雑な理由からComboBoxは、SelectionBoxItemという読み取り専用プロパティを公開しています。 ComboBoxテンプレートのコンテンツプレゼンターは、このプロパティにバインドされます。 非UI要素の文字列表現を公開するのはSelectionBoxItemです。これにより、選択した値を表示できます。 このプロパティを使用すると、コンテンツプレゼンターがデータテンプレートを使用できなくなります。 このため、テンプレートはドロップダウンに適用されますが、選択されたアイテムには適用されません。 この問題を引き起こしている既定のComboBoxテンプレートの一部は次のとおりです。

<ContentPresenter IsHitTestVisible="false"
    Margin="8,1,1,1"
    Content="{TemplateBinding SelectionBoxItem}"
    ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
    ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>

ただし、既定のContentPresenterをオーバーライドし、SelectionItemBoxTemplateの代わりにSelectionBoxItemおよびItemTemplateの代わりにSelectedItemを使用する、独自のComboBoxスタイルを作成できます。 これで問題は解決します。


Answer #2

nameにバインドする代わりにDisplayMemberPathを使用する:

 <Combobox DisplayMemberPath="Name" ... />

おそらく表示される動作の理由は、選択したアイテムのテンプレートに別のプロパティを設定する必要があるからです。http : //msdn.microsoft.com/en-us/library/system.windows.controls.combobox.selectionboxitemtemplate.aspx

アップデート:あなたのコードをチェックせずに私の答えを書いた、ごめんなさい。 今あなたのコードを読んで、あなたがSelectedValueプロパティをバインドしていることに気付きました。 私はこれがあなたの場合にバインドするのに最適なプロパティだとは思わない、通常はプロパティSelectedItemを使用する必要があります。 SelectedValueSelectedItemプロパティが異なる振る舞いをしているため、 SelectedItemを使う傾向があるので、おそらく他の回答に記載されているSelectionBoxItemもので何もする必要がないことを覚えています。 あなたの場合は私もそれを使用します。





combobox