programing

ComboBox에서 null 값을 선택할 수 없는 이유는 무엇입니까?

goodsources 2023. 4. 16. 15:00
반응형

ComboBox에서 null 값을 선택할 수 없는 이유는 무엇입니까?

WPF에서는 (마우스를 사용하여) ComboBox에서 "null" 값을 선택할 수 없습니다.Edit 명확히 하기 위해, 이것은 입니다.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가 있으며, 그 중 하나는 null입니다.창을 Foo 인스턴스로 바인드했습니다.ComboBox에 Bar 속성 값이 표시됩니다.

이 앱을 실행하면 Foo 때문에 ComboBox가 빈 디스플레이로 시작됩니다.기본적으로 막대는 null입니다.괜찮아요.마우스를 사용하여 ComboBox를 드롭다운하고 "Hello" 항목을 선택하면 그것도 작동합니다.그러나 목록 맨 위에 있는 빈 항목을 다시 선택하려고 하면 ComboBox가 닫히고 이전 값인 "Hello"로 돌아갑니다!

화살표 키를 사용하여 null 값을 선택하면 예상대로 동작하며 프로그램적으로 설정도 작동합니다.마우스로만 선택할 수 있지만 동작하지 않습니다.

간단한 회피책은 null을 나타내는 Bar 인스턴스를 가지고 IValue Converter를 통해 실행하는 것입니다만, WPF의 Combo Box에서 null을 마우스로 선택하는 것이 동작하지 않는 이유를 설명해 주실 수 있습니까?

최근에 ComboBox의 null 에서도 같은 문제가 발생했습니다.다음 두 가지 컨버터를 사용하여 해결했습니다.

  1. 아이템의 경우소스 속성: 컬렉션의 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. Selected Value 속성의 경우: 이 속성은 단일 값에 대해 다음 두 가지 방법으로 동일한 작업을 수행합니다.

    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)'}"
    />

결과:

여기에 이미지 설명 입력

주의: Observable Collection에 바인드하면 변경 알림이 손실됩니다.또한 컬렉션에 null 값을 두 개 이상 포함하지 않습니다.

키보드에서 Null "항목"이 전혀 선택되지 않았습니다.이전 항목은 선택 해제되어 후속 항목은 선택되지 않았습니다(선택할 수 있는 항목은 없습니다.따라서 키보드를 사용하여 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에 AddedItems의 빈 배열이 표시되며 "마우스로 "Hello"를 선택하여 null 항목을 선택하면 RemovedItems의 빈 배열이 표시됨을 확인할 수 있습니다.

나는 이 질문에 대한 새로운 해결책을 얻었다."Mahaps 사용 중"

  xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"


  <ComboBox x:Name="bars"  **controls:TextBoxHelper.ClearTextButton="True"**
              DisplayMemberPath="Name" 
              Height="21" 
              SelectedItem="{Binding Bar}"/>

여기에 이미지 설명 입력

여기에 이미지 설명 입력

닫기 버튼을 사용하여 내용을 지울 수 있습니다.

감사해요.

이 답변은 당신이 요구한 것이 아니라는 것을 알지만(마우스와 함께 작동하지 않는 이유에 대한 설명) 전제는 결함이 있다고 생각합니다.

프로그래머 및 사용자로서의 제 관점 (비록)NET)의 늘 값을 선택하는 것은 좋지 않습니다.'무조건'은 자신이 선택한 것이 아니라 가치의 부재를 말합니다.

무언가를 선택하지 않는 기능이 명시적으로 필요한 경우, 말씀하신 회피책("-", "n.a." 또는 "없음"을 값으로 제안합니다.

  • 콤보박스를 비활성화하기 위해 선택되지 않은 체크박스로 콤보박스를 꺼야 합니다.사용자의 관점에서나 프로그래밍적으로나 가장 깔끔한 디자인으로 느껴집니다.

콤보박스에서 null 값을 선택하는 문제에 대한 해결책을 찾기 위해 하루를 보냈습니다.마침내, 다음의 URL에 기재된 기사에서 해결책을 찾았습니다.

http://remyblok.tweakblogs.net/blog/7237/wpf-combo-box-with-empty-item-using-net-4-dynamic-objects.html

public class ComboBoxEmptyItemConverter : IValueConverter 
{ 
/// <summary> 
/// this object is the empty item in the combobox. A dynamic object that 
/// returns null for all property request. 
/// </summary> 
private class EmptyItem : DynamicObject 
{ 
    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
        // just set the result to null and return true 
        result = null; 
        return true; 
    } 
} 

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
    // assume that the value at least inherits from IEnumerable 
    // otherwise we cannot use it. 
    IEnumerable container = value as IEnumerable; 

    if (container != null) 
    { 
        // everything inherits from object, so we can safely create a generic IEnumerable 
        IEnumerable<object> genericContainer = container.OfType<object>(); 
        // create an array with a single EmptyItem object that serves to show en empty line 
        IEnumerable<object> emptyItem = new object[] { new EmptyItem() }; 
        // use Linq to concatenate the two enumerable 
        return emptyItem.Concat(genericContainer); 
    } 

    return value; 
} 

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
    throw new NotImplementedException(); 
} 

}

 <ComboBox ItemsSource="{Binding  TestObjectCollection, Converter={StaticResource ComboBoxEmptyItemConverter}}" 
      SelectedValue="{Binding SelectedID}" 
      SelectedValuePath="ID" 
      DisplayMemberPath="Name" />

이것이 당신의 대답을 완전히 해결하지는 못할 수도 있지만, 바라건대 올바른 방향으로의 히트입니다.

  1. SP1은 설치되었습니까?

Scott Gu의 블로그에서:

  • .5 에는 NET 3.5 SP1에 대한 데이터 및 이 몇 되었습니다.
    WPF입니다.
  • {{Binding }} 식 내에서 StringFormat을 지원하여 바인딩된 값의 형식을 쉽게 지정할 수 있습니다.
  • ItemsControl에서 파생된 컨트롤 내에서 새로운 교대 행 지원: 행의 교대 속성을 더 쉽게 설정할 수 있습니다(예: 교대 배경색).
  • 편집 가능한 컨트롤의 null 값에 대한 처리변환 지원 향상 유효성 검사 규칙을 전체 바인딩 항목에 적용하는 항목 수준 검증
  • 멀티 셀렉터 지원으로 멀티 셀렉터 및 일괄 편집 시나리오에 대응
  • IEdable Collection 데이터 컨트롤을 데이터 소스와 인터페이스하여 트랜잭션 방식으로 항목 편집/추가/삭제 가능
  • IEnumberable 데이터 소스에 바인딩 시 성능 향상

제가 시간을 낭비해서 죄송합니다. 그리고 이 일은 가깝지도 않았습니다.문제는 다음에서 유전된다고 생각합니다.

강력한 유형 데이터 집합의 제약 조건

여기서 Null Value Data Set에 대해 설명합니다.

하지만 이제 SP1 for 입니다.Net 3.5는 이 문제에 대응하고 있어야 합니다.

컬렉션 아이템에 가치 속성을 추가하는 것과 같은 문제가 있었습니다.

 public class Bar

   {
      public string Name { get; set; }
      public Bar Value
      {
         get { return String.IsNullOrEmpty(Name) ?  null :  this; } // you can define here your criteria for being null
      }
   }

그런 다음 null 대신 항목을 추가할 때 동일한 개체를 사용합니다.

  comboBox1.ItemsSource=  new ObservableCollection<Bar> 
        {
            new Bar(),
            new Bar { Name = "Hello" }, 
            new Bar { Name = "World" } 
        };

selected item 대신 selected value에 바인드합니다.

<ComboBox Height="23" Margin="25,40,133,0" DisplayMemberPath="Name"
              SelectedValuePath="Value" 
              SelectedValue="{Binding Bar}"
              Name="comboBox1" VerticalAlignment="Top" />

완전한 솔루션은 아니지만 하나의 회피책만 사용합니다.

바인딩을 시도합니다.폴백 값

WPF의 데이터 바인딩에 대해 몰랐을 것부터6가지

ComboBox는 아무리 단순해도 항목을 표시하려면 DataTemplate가 필요합니다.Data Template는 다음과 같이 동작합니다.인스턴스에서 값을 가져옵니다.[path], 예:

bar1.Car.Color

따라서 값을 얻을 수 없습니다.

null.Car.Color

Null 참조 예외가 발생합니다.따라서 늘 인스턴스는 표시되지 않습니다.그러나 Color(참조 유형인 경우)는 예외 없이 null로 허용됩니다.

추측일 뿐이지만, 합리적인 것 같아요.

콤보박스가 항목 컬렉션으로 "ListCollectionView"(lcv)를 사용하고 있다고 가정합니다.당신이 프로그래머라면 무엇을 할 건가요?

키보드와 마우스 모두 담당합니다.

키보드 입력을 받으면

lcv.MoveCurrentToNext();

또는

lcv.MoveCurrentToPrevious();

키보드가 잘 작동하는 게 확실해요.

그리고 마우스 입력에 대한 응답 작업을 하고 있습니다.그리고 그게 문제가 된다.

  1. 내 아이템의 'Mouse Click' 이벤트를 듣고 싶다.그러나 내 아이템은 생성되지 않고 플레이스홀더일 수 있습니다.사용자가 이 자리 표시자를 클릭해도 아무것도 표시되지 않습니다.

  2. 제가 이벤트를 성공적으로 받으면 그 다음은 뭘까요?호출합니다.

    lcv.MoveCurrentTo(selectedItem);

여기서 null이 되는 "selected Item"은 허용 가능한 파라미터가 아니라고 생각합니다.

어쨌든, 그건 그냥 추측일 뿐이야.디버깅할 시간은 없지만 디버깅할 시간은 없습니다.고쳐야 할 결함들이 많아요.행운을 빌어요.:)

언급URL : https://stackoverflow.com/questions/518579/why-cant-i-select-a-null-value-in-a-combobox

반응형