6

プロパティ ItemsSource と SelectedValue がモデルにバインドされている ComboBox があります。モデルで選択したアイテムを別のアイテムに調整する必要がある場合がありますが、モデルでそれを行うと、SelectedValue が適切に設定されていても (snoop と SelectionChanged の両方でチェックされます)、モデルの値がビューに反映されません。イベント ハンドラー)。

問題を説明するために、単純な xaml を次に示します。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
      <ComboBox Height="25" Width="120" SelectedValue="{Binding SelectedValue}" SelectedValuePath="Key" ItemsSource="{Binding PossibleValues}" DisplayMemberPath="Value"/>
   </Grid>
</Window>

そして、ここにモデルがあります:

using System.Collections.Generic;
using System.Windows;
using System.ComponentModel;

namespace WpfApplication1
{
   public partial class MainWindow : Window, INotifyPropertyChanged
   {
      int m_selectedValue = 2;
      Dictionary<int, string> m_possibleValues = new Dictionary<int, string>() { { 1, "one" }, { 2, "two" }, { 3, "three" }, {4,"four"} };

      public int SelectedValue
      {
         get { return m_selectedValue; }
         set 
         {
            if (value == 3)
            {
               m_selectedValue = 1;
            }
            else
            {
               m_selectedValue = value;
            }
            PropertyChanged(this, new PropertyChangedEventArgs("SelectedValue"));
         }
      }
      public Dictionary<int, string> PossibleValues
      {
         get { return m_possibleValues; }
         set { m_possibleValues = value; }
      }


      public MainWindow()
      {
         InitializeComponent();
      }

      public event PropertyChangedEventHandler PropertyChanged;
   }
}

動作は次のようになると予想しました。

  1. 最初は2人選択
  2. 「1つ」を選択 -> コンボボックスに「1つ」が表示されます
  3. 「2」を選択 -> コンボボックスに「2」が表示されます
  4. "three" を選択 -> ComboBox に " one "が表示されます
  5. "four" を選択 -> ComboBox に "four" が表示されます

ただし、#4 では「3」が表示されます。なんで?モデルの値は 1 (「1」) に変更されましたが、ビューには引き続き 3 (「3」) が表示されます。

SelectionChanged イベント ハンドラーでバインディング ターゲットを明示的に更新することで回避策を見つけましたが、これは間違っているようです。これを達成する別の方法はありますか?

4

2 に答える 2

6

項目を選択すると、バインディング エンジンはモデルを更新しPropertyChanged、プロパティ セッターの呼び出し中に変更されたばかりのプロパティを無視します。そうしないと、無限ループに陥る可能性があります。

システムは、セッターが渡された値を変更しないと想定しています。ここでの回避策は簡単です。バインディングを使用Dispatcher.BeginInvoke()または設定IsAsync=Trueして、探している動作を取得します。ただし、個人的には、これを行うことは強くお勧めしません。タイミングに関連する多くの新しい問題が発生するだけでなく、主に、そもそも存在しないはずの問題の回避策であるためです。

これをしないでください。これは WPF に適用されるだけではありません。セッターを変更すると、設定したばかりの値が正しく設定され、例外がスローされないことが期待できます。セッター内の値を変更するのは直観に反しており、後で噛まれる可能性があります。さらに、アプリケーションのユーザーが、コンボボックスがその選択を無視しているのを見ると、非常に不快になる可能性があります。

渡される値が気に入らない場合は、例外をスローし、使用Binding.ValidatesOnExceptionsして WPF にそれが期待されていることを伝えます。ユーザーにこの値を選択させたくない場合は、最初からリストに含めないでください。他のビジネス ルールのために条件付きでアイテムを使用できない場合は、リストを動的にフィルター処理するか、トリガーを適用します。

于 2012-04-09T21:58:13.177 に答える
2

SelectedValueコントロールのおよび/またはSelectedItemプロパティにバインドするときに、コントロールの適切な更新に関して永続的な問題がありましたComboBox

SelectedIndexこれを解決するには、代わりにプロパティにバインドする必要がありました。ViewModel で 'index' プロパティを処理するのは面倒でしたが、ComboBox更新されないという問題は解決しました。

于 2012-04-09T21:30:50.410 に答える