2013-03-21 19 views
8

私の質問は基本的にthis oneです。私は、問題を再現しやすくするために、より多くの情報とコードを提供するのに役立つと考えました。 からMicrosoft.Windows.Controls.Ribbon.RibbonComboBoxを操作すると、バグの多い大きなボグを歩いているように感じるのではなく、周囲の道を知っていればあなたがすることではありません。RibbonComboBoxのSelectedItemをデータバインドする方法

Anything。私が遭遇した最大の問題は、SelectedItemのデータバインディングでした。

私は(私が約RibbonGallery?を見つけた後で)私が始めたことは次のとおりです。 ItemsSourceとSelectedItemをComboBoxのサブ要素に持たせるために、同じレベルでさえすでに私にheebie-jeebiesを与えましたが、それは正しいようです。

このアプリケーションでは、ViewModelのコンストラクタでSelectedItemを設定しています。ただし、アプリを実行すると、SelectedItemは表示されません。 VSデザイナーでも「第2の選択肢」が正しく表示されています。

実行アプリ:Running App VSのデザイナーは:Visual Studio Designer

のSelectedItemセッターをデバッグするには、複数のパスに気付くでしょう。 ctor(1、以下のデバッグログを参照)の "second option"に最初に設定した後は、null(2)にリセットされます(外部コードによって、コントロール自体で計算されます)。 UIでドロップダウンを開くと、再びnullに設定され(3)、次に値を選択するとこの値(4,5)に2回設定されます。私は「第2の選択肢」を選択し、「第1の選択肢」(6-9)で手順を繰り返した。これは、(リボンコントロール...から1001のバインディング例外を無視して)次のログを生成:

enter image description here

明らかに(2)、私の最初の選択をリセットされている大きな問題。コントロールが最初に表示されたときのように、リセットされます。非常に醜い回避策は、タイマーで値を設定することです。このコントロールのLoadedイベントで設定すると、このサンプルアプリケーションでは私にとってはうまくいくが、実際の重いアプリではそうはならない。とにかく、それはすべて間違っていると感じます。誰かがより良い解決策を知っていますか?

XAML:

<UserControl x:Class="WpfApplication1.RibbonComboBoxDemo" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:r="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon" 
      xmlns:local="clr-namespace:WpfApplication1" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 

    <UserControl.DataContext> 
     <local:ViewModel /> 
    </UserControl.DataContext> 

    <Grid> 
     <r:Ribbon > 
      <r:RibbonTab Header="First Tab"> 
       <r:RibbonGroup Header="Group"> 
        <r:RibbonComboBox > 
         <r:RibbonGallery SelectedItem="{Binding SelectedItem, Mode=TwoWay}"> 
          <r:RibbonGalleryCategory ItemsSource="{Binding Controls}" DisplayMemberPath="Caption" /> 
         </r:RibbonGallery> 
        </r:RibbonComboBox> 
       </r:RibbonGroup> 
      </r:RibbonTab> 
      <r:RibbonTab Header="Second Tab" /> 
     </r:Ribbon> 
    </Grid> 
</UserControl> 

のViewModel:

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Diagnostics; 

namespace WpfApplication1 
{ 
    public class ViewModel : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 
     private void OnPropertyChanged(string propertyName) 
     { 
      if (this.PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 

     public ObservableCollection<ControlBaseModel> Controls { get; private set; } 


     private ControlBaseModel _selectedItem; 
     public ControlBaseModel SelectedItem { get { return _selectedItem; } set { LogSelectedItemChange(value); _selectedItem = value; OnPropertyChanged("SelectedItem"); } } 

     public ViewModel() 
     { 
      this.Controls = new ObservableCollection<ControlBaseModel>(); 

      this.Controls.Add(new ControlBaseModel() { Caption = "first option" }); 
      this.Controls.Add(new ControlBaseModel() { Caption = "second option" }); 

      this.SelectedItem = this.Controls[1]; // set to second option 
     } 

     int i = 0; 
     private void LogSelectedItemChange(ControlBaseModel value) 
     { 
      i++; 
      string setObject = "null"; 
      if (value != null) 
      { 
       setObject = value.Caption; 
      } 
      Debug.WriteLine(string.Format("{0}: SelectedItem.set(): {1}", i, setObject)); 
     } 

    } 

    public class ControlBaseModel : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 
     private void OnPropertyChanged(string propertyName) 
     { 
      if (this.PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 

     private string _name; 
     public string Name { get { return _name; } set { _name = value; OnPropertyChanged("Name"); } } 

     private string _caption; 
     public string Caption { get { return _caption; } set { _caption = value; OnPropertyChanged("Caption"); } } 
    } 
} 

答えて

5

コンボボックスのSelectedItemは自分のアプリケーションにnullにリセットされる前にロードされたイベントが発生しているビュー/ユーザーコントロールは、コンボボックスロードされたイベントは、実際にある間二度発射され、二度目は "遅く"発射される。だから私は良い方のために喜んで捨てます私の現在のソリューションは、これです:

<r:RibbonComboBox> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="Loaded"> 
      <i:InvokeCommandAction Command="{Binding LoadedCommand}" /> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
    <r:RibbonGallery SelectedItem="{Binding SelectedItem, Mode=TwoWay}"> 
     <r:RibbonGalleryCategory ItemsSource="{Binding Controls}" DisplayMemberPath="Caption"/> 
    </r:RibbonGallery> 
</r:RibbonComboBox> 

のViewModel:

private ControlBaseModel _lastNonNullSelectedItem; 

public ObservableCollection<ControlBaseModel> Controls { get; private set; } 

private ControlBaseModel _selectedItem; 
public ControlBaseModel SelectedItem 
{ 
    get { return _selectedItem; } 
    set 
    { 
     if (value != null) { _lastNonNullSelectedItem = value; } 
     _selectedItem = value; 
     OnPropertyChanged("SelectedItem"); 
    } 
} 
public ICommand LoadedCommand { get; private set; } 


public ViewModel() 
{ 
    this.Controls = new ObservableCollection<ControlBaseModel>(); 
    this.LoadedCommand = new ActionCommand(OnLoaded); // ActionCommand: simple implementation of ICommand 

    this.Controls.Add(new ControlBaseModel() { Caption = "first option" }); 
    this.Controls.Add(new ControlBaseModel() { Caption = "second option" }); 

    this.SelectedItem = this.Controls[1]; // set to second option 
} 

private void OnLoaded() 
{ 
    this.SelectedItem = _lastNonNullSelectedItem; 
} 
+0

使用して...本当にありがとう !!! –

2

私はちょうど標準コンボボックスを使用して終了しました。

<ComboBox SelectedItem="{Binding Item}" ItemsSource="{Binding Items}"/> 

あなたがRibbonComboBoxと同じ(非常によく似た)スタイルをしたい場合、あなたは私に膨大な時間を保存し

<ComboBox IsEditable="True" IsReadOnly="True" SelectedItem="{Binding Item}" ItemsSource="{Binding Items}"/> 
関連する問題