44

アップデート

少し調べた後。問題と思われるのは、Item ソースの読み込みが完了する前に SelectedValue/SelectedItem が発生していることです。ブレークポイントに座って数秒待つと、期待どおりに動作します。どうやってこれを回避するのかわかりません。

更新終了

ComboBoxでMVVMを使用してWPFで使用するアプリケーションがあります。以下はViewModelの例です。私が抱えている問題は、ページを離れて元に戻すときに、ComboBox が選択されている現在の値を選択していないことです。

モデルを見る

public class MyViewModel
{
     private MyObject _selectedObject;
     private Collection<Object2> _objects;
     private IModel _model;

     public MyViewModel(IModel model)
    {
         _model = model;
         _objects = _model.GetObjects();
    }

    public Collection<MyObject> Objects
    {
         get
         {
              return _objects;
         }
         private set
         {
              _objects = value;
         }
     }

     public MyObject SelectedObject
     {
          get
          {
              return _selectedObject;
          }
          set
          {
               _selectedObject = value;
          }
      }
 }

この例では、MyObject に 2 つのプロパティ (Text と Id) があるとします。ComboBox の XAML は次のようになります。

XAML

<ComboBox Name="MyComboBox" Height="23"  Width="auto" 
    SelectedItem="{Binding Path=SelectedObject,Mode=TwoWay}" 
    ItemsSource="{Binding Objects}"
    DisplayMemberPath="Text"
    SelectedValuePath="Id">

ページに戻ってオブジェクトが再構築されたときにこれをどのように構成しても、ComboBox は値を選択しません。ただし、オブジェクトはプロパティの get を介して正しいオブジェクトを返しています。

これが単に ComboBox と MVVM パターンの動作の問題なのかどうかはわかりません。行っているテキスト ボックスのバインディングは正しく機能します。

4

18 に答える 18

43

設定IsSynchronizedWithCurrentItem="True"がうまくいきました!

于 2012-06-26T06:58:57.873 に答える
21

SelectedItem プロパティの前に ItemsSource プロパティを配置する必要があります。数日前にこの問題について言及しているブログに出くわしました。

于 2011-01-13T02:45:09.390 に答える
11

同様の問題がありましたが、IEquatableを適切に実装していることを確認することで解決しました。バインドが発生すると、オブジェクトが一致するかどうかを確認しようとするため、等価チェックを適切に実装していることを確認してください。

于 2009-03-19T21:50:55.733 に答える
10

この場合、オブジェクトのハッシュIDが異なるため、selecteditemバインドは機能しません。

考えられる解決策の1つは次のとおりです。

選択したアイテムIDに基づいて、itemsourceコレクションのオブジェクトを回復し、選択したアイテムのプロパティをそれに設定します。

例:

<ctrls:ComboBoxControlBase SelectedItem="{Binding Path=SelectedProfile, Mode=TwoWay}" ItemsSource="{Binding Path=Profiles, Mode=OneWay}" IsEditable="False" DisplayMemberPath="Name" />

ItemSourceにバインドされたプロパティは次のとおりです。

public ObservableCollection<Profile> Profiles
{
   get { return this.profiles; }
   private set { profiles = value; RaisePropertyChanged("Profiles"); }
}

SelectedItemにバインドされるプロパティは次のとおりです。

public Profile SelectedProfile 
{
    get { return selectedProfile; }
    set
    {
        if (this.SelectedUser != null)
        {
            this.SelectedUser.Profile = value; 
            RaisePropertyChanged("SelectedProfile");  
        } 
    } 
}

リカバリコードは次のとおりです。

    [Command("SelectionChanged")]
    public void SelectionChanged(User selectedUser)
    {
        if (selectedUser != null)
        {
            if (selectedUser is User)
            {
                if (selectedUser.Profile != null)
                {
                    this.SelectedUser = selectedUser;
                    this.selectedProfile = this.Profiles.Where(p => p.Id == this.SelectedUser.Profile.Id).FirstOrDefault();
                    MessageBroker.Instance.NotifyColleagues("ShowItemDetails"); 
                }
            }
        }            
    }

お役に立てば幸いです。答えを探すのに多くの時間を費やしましたが、見つかりませんでした。

于 2012-10-03T19:32:49.427 に答える
4

現在のページを離れるとき、のプロパティにCollectionView関連付けられているものは削除されます。また、プロパティはデフォルトでtrueであるため、およびプロパティはリセットされます。 これは、バインディングの内部データ型の問題のようです。他の人が上で示唆したように、代わりにビューモデルのintプロパティにバインドして使用すると、機能します。2つのMyObjectを比較するときに実際のプロパティが比較されるように、MyObjectの演算子をオーバーライドするのが簡単です。ItemsSourceComboBoxComboBox IsSyncronizedWithCurrentSelectedItemSelectedValue
SelectedValueEqualsId

別のヒント:ビューモデルを再構築してを使用する場合は、がであるSelectedValue場合にのみ使用してください。文字列キーを使用する場合は、の代わりにのプロパティにバインドします。SelectedValuePath=IdIdintTextComboBoxSelectedValue

于 2011-02-17T20:01:11.963 に答える
3

私も以前にこの動作に気付きました。SelectedIndex プロパティでは同じバグが発生しないことに気付きました。ViewModel を再構築して、選択した項目のインデックスを公開し、それにバインドできる場合は、問題ありません。

于 2009-03-20T21:30:28.347 に答える
2

私も同じ問題を抱えていました。事はです。選択された項目は、コレクションからどのオブジェクトを使用する必要があるかを認識していません。そのため、コレクションのアイテムを使用するには、選択したアイテムに指示する必要があります。

public MyObject SelectedObject
 {
      get
      {
          Objects.find(x => x.id == _selectedObject.id)
          return _selectedObject;
      }
      set
      {
           _selectedObject = value;
      }
 }

これが役立つことを願っています。

于 2010-05-14T15:21:56.680 に答える
2

UserControl_Loaded イベントにディスパッチャを追加して問題を解決しました

 Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
 {
     combobox.SelectedIndex = 0;
 }));
于 2014-08-16T20:48:07.533 に答える
2

この問題に対する非常に簡単な答えがあります。まず、ビュー IsSynchronizedWithCurrentItem="True" に次のコードを追加します。

次に、ViewModel の新しいオブジェクトをそのプロパティに割り当てるときはいつでも、SelectedObject をプライベート メンバーではなく、そのプロパティに保存する必要があります。

ビューモデル プロパティは次のようになります。

    public Role SelectedObject 
    {
        get { return object; }
        set
        {
            if (value != null)
            {
                if (!object.Equals(value))
                {
                    object = value;
                    OnPropertyChanged(() => SelectedObject );
                }
            }
        }
    }

これで問題が解決するはずです。

于 2011-08-04T17:57:09.587 に答える
1

IsSyncronizedWithCurrent=Falseはそれを機能させます。

于 2010-12-08T07:38:35.423 に答える
1

私はしばらくの間、この問題と戦っていました。私の場合、アイテム ソースとして複合型 (リスト) を使用し、選択した値として KeyType を使用していました。ロード イベントで、KeyType が null に設定されていました。これにより、すべてが壊れました。キーが変更されたときにサブ要素は更新されません。KeyType の提案された値が null でないことを確認するチェックを追加すると、すべてが期待どおりに機能することがわかりました。

    #region Property: SelectedKey
    // s.Append(string.Format("SelectedKey : {0} " + Environment.NewLine, SelectedKey.ToString()));

    private KeyType _SelectedKey = new KeyType();
    public KeyType SelectedKey
    {
        get { return _SelectedKey; }
        set
        {
            if(value != null )
                if (!_SelectedKey.Equals(value))
                {
                    _SelectedKey = value;
                    OnPropertyChanged("SelectedKey");
                }
        }
    }
    #endregion SelectedKey
于 2011-02-08T23:42:56.557 に答える
1

色のリスト( List<Brush> )を表示する ComboBox でこの問題が発生しました。
色を選択することはできましたが、選択を閉じたときに表示されませんでした (ただし、プロパティは変更されました!)

修正は、ComboBox (Brush) で選択された型の Equals(object obj) メソッドを上書きしていました。これは、Brush が封印されているため単純ではありませんでした。そこで、ブラシを含み、Equals を実装するクラスEqualityBrushを作成しました。

public class EqualityBrush
{
    public SolidColorBrush Brush { get; set; }

    public override bool Equals(object o)
    {
        if (o is EqualityBrush)
        {
            SolidColorBrush b = ((EqualityBrush)o).Brush;
            return b.Color.R == this.Brush.Color.R && b.Color.G == this.Brush.Color.G && b.Color.B == this.Brush.Color.B;
        }
        else
            return false;
    }
}

通常の Brush クラスの代わりに、新しい EqualityBrush クラスの List を使用すると、問題が解決しました!

私のコンボボックスXAMLは次のようになります。

<ComboBox ItemsSource="{Binding BuerkertBrushes}" SelectedItem="{Binding Brush, Mode=TwoWay}" Width="40">
    <ComboBox.Resources>
        <DataTemplate DataType="{x:Type tree:EqualityBrush}">
            <Rectangle Width="20" Height="12" Fill="{Binding Brush}"/>
        </DataTemplate>
    </ComboBox.Resources>
</ComboBox>

ViewModelの "Brush" プロパティはEqualityBrush 型でなければならないことを思い出してください。

于 2012-01-11T16:52:32.487 に答える
0

Loadedイベントを使用します。

private void cmb_Loaded(object sender, RoutedEventArgs e) {
    if (cmb.Items.Count > 0) cmb.SelectedIndex = 0;          
}

わたしにはできる。

于 2011-02-01T13:48:59.500 に答える
0

ComboBox.SelectionBoxItem.ToString()

于 2010-06-28T10:32:28.237 に答える
0

DataContext を Page に適用する方法である可能性があります。WPF では、ページに移動するたびに、すべてが再初期化され、コンストラクターが呼び出され、メソッドが読み込まれます。したがって、ビュー内で DataContext を設定している場合、ユーザーが選択した SelectedItem を吹き飛ばすことは間違いありません。これを避けるには、ページの KeepAlive プロパティを使用します。

<Page KeepAlive="True" ...>
   ...
</Page>

これにより、すでにアクセスしたページに戻るときに Loaded イベントのみが発生します。そのため、Load ではなく、Initialize (外部またはコンストラクター内) で DataContext を設定していることを確認する必要があります。

ただし、これは Page のそのインスタンスに対してのみ機能します。そのページの新しいインスタンスに移動すると、そのコンストラクターが再度呼び出されます。

于 2009-03-21T14:42:54.513 に答える