48

WPF では、ComboBox から "null" 値を (マウスで) 選択することはできないようです。編集明確にするために、これは.NET 3.5 SP1です。

ここに私が何を意味するかを示すコードがあります。まず、C# 宣言:

public class Foo
{
    public Bar Bar { get; set; }
}

public class Bar 
{
    public string Name { get; set; }
}

次に、私の Window1 XAML:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <ComboBox x:Name="bars" 
                  DisplayMemberPath="Name" 
                  Height="21" 
                  SelectedItem="{Binding Bar}"
                  />
    </StackPanel>
</Window>

そして最後に、私の Window1 クラス:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();

        bars.ItemsSource = new ObservableCollection<Bar> 
        {
            null, 
            new Bar { Name = "Hello" }, 
            new Bar { Name = "World" } 
        };
        this.DataContext = new Foo();
    }
}

私と一緒に?項目が Bar インスタンスのリストにバインドされている ComboBox があり、そのうちの 1 つは null です。ウィンドウを Foo のインスタンスにバインドし、ComboBox はその Bar プロパティの値を表示しています。

このアプリを実行すると、デフォルトで Foo.Bar が null であるため、ComboBox は空の表示で開始されます。それはいいです。マウスを使用して ComboBox をドロップダウンし、「Hello」項目を選択すると、それも機能します。しかし、リストの一番上にある空の項目を再度選択しようとすると、ComboBox が閉じて、以前の値の "Hello" に戻ります!

矢印キーで null 値を選択すると期待どおりに機能し、プログラムで設定することもできます。動作しないのはマウスで選択することだけです。

簡単な回避策は、null を表す Bar のインスタンスを作成し、それを IValueConverter で実行することだとわかっていますが、マウスで null を選択しても WPF の ComboBox で機能しない理由を誰かが説明できますか?

4

10 に答える 10

19

最近、 ComboBoxのnull値で同じ問題に遭遇しました。2つのコンバーターを使用して解決しました:

  1. ItemsSourceプロパティの場合:コレクション内のnull値を、コンバーターのパラメーター内で渡される任意の値に置き換えます。

    class EnumerableNullReplaceConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var collection = (IEnumerable)value;
    
            return
                collection
                .Cast<object>()
                .Select(x => x ?? parameter)
                .ToArray();
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
    
  2. SelectedValueプロパティの場合: これは同じことを行いますが、単一の値に対して次の 2 つの方法で行います。

    class NullReplaceConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value ?? parameter;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value.Equals(parameter) ? null : value;
        }
    }
    

使用例:

<ComboBox 
    ItemsSource="{Binding MyValues, Converter={StaticResource EnumerableNullReplaceConverter}, ConverterParameter='(Empty)'}" 
    SelectedValue="{Binding SelectedMyValue, Converter={StaticResource NullReplaceConverter}, ConverterParameter='(Empty)'}"
    />

結果:

ここに画像の説明を入力

注: ObservableCollectionにバインドすると、変更通知が失われます。また、コレクションに複数のnull値を持たせたくありません。

于 2015-04-28T13:50:24.640 に答える
16

ヌルの「アイテム」はキーボードでまったく選択されていません。むしろ、前のアイテムが選択解除されており、後続のアイテムは選択されていません。 これが、キーボードで null 項目を「選択」した後、以前に選択した項目 (「Hello」) を再選択できない理由です (マウスを使用する場合を除く)。

つまり、ComboBox で null アイテムを選択または選択解除することはできません。そうしていると思うときは、前のアイテムまたは新しいアイテムの選択を解除または選択していることになります。

これは、ComboBox 内の項目に背景を追加することで、おそらく最もよく確認できます。「Hello」を選択すると、ComboBox の背景色が色付きになりますが、キーボードで選択を解除すると、背景色が消えます。マウスでリストをドロップダウンすると、null アイテムには実際に背景色があるため、これが null アイテムではないことはわかっています。

元の質問から変更された次の XAML は、アイテムの背後に LightBlue の背景を配置するため、この動作を確認できます。

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <ComboBox x:Name="bars" Height="21" SelectedItem="{Binding Bar}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <Grid Background="LightBlue" Width="200" Height="20">
                        <TextBlock Text="{Binding Name}" />
                    </Grid>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </StackPanel>
</Window>

さらに検証が必要な場合は、ComboBox で SelectionChanged イベントを処理し、「null アイテムを選択する」と実際にその SelectionChangedEventArgs に追加された項目の空の配列が与えられ、「マウスで 'Hello' を選択して null アイテムを選択解除する」ことを確認できます。 RemovedItems の空の配列を返します。

于 2009-12-14T23:12:38.767 に答える
7

この答えはあなたが求めたものではないことは知っていますが(マウスで機能しない理由の説明)、前提に欠陥があると思います:

プログラマーおよびユーザー(.NETではない)としての私の観点からは、null値を選択することは悪いことです。「null」は、選択したものではなく、値がないことを意味します。

何かを明示的に選択しない機能が必要な場合は、言及した回避策(値として「-」、「na」、または「none」)、またはそれ以上の方法をお勧めします。

  • コンボボックスを無効にするためにチェックを外すことができるチェックボックスでコンボボックスをラップします。これは、ユーザーの観点からもプログラム的にも、最もクリーンなデザインだと思います。
于 2009-02-17T08:08:03.387 に答える
1

これはあなたの答えに完全に対応していないかもしれませんが、うまくいけば正しい方向へのヒットです:

  1. SP1をインストールしましたか?

Scott Gu のブログから:


  • NET 3.5 SP1 には、 WPFに対するデータ バインディングと編集の改善点がいくつか含まれています。これらには以下が含まれます:
  • {{ Binding }} 式内での StringFormat サポートにより、バインドされた値を簡単にフォーマットできます
  • ItemsControl から派生したコントロール内での新しい交互行のサポートにより、行に交互のプロパティを簡単に設定できます (例: 交互の背景色)
  • 編集可能なコントロールでの null 値の処理と変換のサポートの改善 バインドされたアイテム全体に検証ルールを適用するアイテム レベルの検証
  • 複数選択および一括編集シナリオを処理するための MultiSelector サポート
  • IEditableCollectionView のサポートにより、データ コントロールをデータ ソースに接続し、トランザクション方式でアイテムの編集/追加/削除を可能にします
  • IEnumerable データ ソースにバインドする際のパフォーマンスの向上

私があなたの時間を無駄にして申し訳ありません..しかし、問題は次のものから継承されていると思います:

厳密に型指定されたデータセットの制約

ここで説明されている NullValueDataSet

しかし、現在、.Net 3.5 の SP1 はこの問題に対処しているはずです..

于 2009-02-06T00:49:06.967 に答える
0

ComboBoxには、アイテムがどれほど単純であっても、アイテムを表示するためのDataTemplateが必要です。DataTemplateは次のように機能します。instance。[path]から値を取得します。例:

bar1.Car.Color

したがって、から値を取得することはできません

null.Car.Color

null参照例外をスローします。したがって、nullインスタンスは表示されません。ただし、この場合は例外がないため、色(参照型の場合)はnullにすることができます。

于 2009-02-17T07:41:47.630 に答える
0

ただの推測ですが、それは合理的に聞こえると思います。

コンボボックスがアイテムコレクションとして「ListCollectionView」(インスタンスとしてlcv)を使用していると仮定します。あなたがプログラマーなら、あなたは何をするつもりですか?

キーボードとマウスの両方に対応します。

キーボード入力を取得したら、

lcv.MoveCurrentToNext();

また

lcv.MoveCurrentToPrevious();

だから、キーボードがうまく機能することを確認してください。

それから私は応答マウス入力に取り組んでいます。そしてそれが問題になります。

  1. アイテムの「MouseClick」イベントを聴きたいです。しかし、おそらく、私のアイテムは生成されません。それは単なるプレースホルダーです。したがって、ユーザーがこのプレースホルダーをクリックしても、何も表示されません。

  2. イベントが正常に行われたら、次は何ですか。呼び出します

    lcv.MoveCurrentTo(selectedItem);

nullになる「selectedItem」は、ここでは受け入れ可能なパラメータではないと思います。

とにかく、それはただの推測です。デバッグすることはできますが、デバッグする時間がありません。修正すべき欠陥がたくさんあります。幸運を。:)

于 2009-02-17T09:01:44.413 に答える
0

Binding.FallbackValue を試す

WPF のデータ バインディングについて知らなかった 6 つの事柄から

于 2009-02-06T13:32:13.853 に答える