簡體   English   中英

在ComboBox中輸入垃圾時,將SelectedValue設置為0

[英]Set SelectedValue to 0 when garbage is entered in ComboBox

我有一個簡單的ComboBox,如下所示:

<ComboBox ItemsSource="{DynamicResource ItemsCompColl}" 
          TextSearch.TextPath="ItemName"
          SelectedValue="{Binding ItemId, UpdateSourceTrigger=PropertyChanged, 
                                  ValidatesOnDataErrors=True}" SelectedValuePath="ItemId"
          Grid.IsSharedSizeScope="True">

    ........................

</ComboBox>

它運作良好。 現在,我正在使用SelectedValue中綁定的ItemId屬性來檢查用戶是否從comboBox中選擇了適當的項目。

問題:

當用戶從ComboBox中選擇一個值時,ItemId屬性將設置為ComboBox中Selected Item的ID。 之后,如果用戶轉到下一個控件並返回到ComboBox,並向ComboBox輸入一些垃圾值,則ComboBox的ItemId不會更改,這意味着它不會重置為“ 0”。 因此,我的驗證失敗,並且用戶成功輸入了垃圾值。

好的,因此當ComboBox的可編輯TextBox中發生任何驗證錯誤時,您希望將SelectedValue設置為0。 您需要檢查Text的驗證結果,然后在驗證失敗的情況下將SelectedValue重置為0。

這是一個適合您的示例:

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">
    <Grid>
        <StackPanel>
            <ComboBox ItemsSource="{Binding ComboboxItems}" 
                      IsEditable="True" DisplayMemberPath="ItemName"
                      Text="{Binding SelectedName, ValidatesOnDataErrors=True}"
                      SelectedValue="{Binding SelectedID, UpdateSourceTrigger=PropertyChanged}" 
                      SelectedValuePath="ItemId"
                      Grid.IsSharedSizeScope="True">                
            </ComboBox>
            <TextBox Text="{Binding SelectedID,UpdateSourceTrigger=PropertyChanged}"/>
        </StackPanel>
    </Grid>
</Window> 

C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;    
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        MyViewModel mvm;
        public MainWindow()
        {
            InitializeComponent();
            mvm = new MyViewModel()
            {
                ComboboxItems = new ObservableCollection<ComboItem>() 
                { 
                    new ComboItem{ItemName="item1",ItemId=1},
                    new ComboItem{ItemName="item2",ItemId=2},
                    new ComboItem{ItemName="item3",ItemId=3}
                },
            };
            this.DataContext = mvm;
        }
    }
    public class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            var handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        protected void RaisePropertyChanged(String propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
    }


    public class ComboItem : ObservableObject
    {
        private string _itemname;
        private int _itemid;
        public string ItemName
        {
            get
            {
                return _itemname;
            }
            set
            {
                _itemname = value;
                RaisePropertyChanged("ItemName");
            }
        }

        public int ItemId
        {
            get { return _itemid; }
            set
            {
                _itemid = value;
                RaisePropertyChanged("ItemId");
            }
        }
    }

    public class MyViewModel : ObservableObject, IDataErrorInfo
    {
        private int _selectedid;
        private string _selectedname;
        public ObservableCollection<ComboItem> ComboboxItems
        {
            get;
            set;
        }


        public int SelectedID
        {
            get { return _selectedid; }
            set
            {
                if (_selectedid != value)
                {
                    _selectedid = value;
                    RaisePropertyChanged("SelectedID");

                }
            }
        }
        public string SelectedName
        {
            get { return _selectedname; }
            set
            {
                if (_selectedname != value)
                {
                    _selectedname = value;
                    RaisePropertyChanged("SelectedName");

                }
            }
        }   

        public string Error
        {
            get { return this[SelectedName]; }
        }

        public string this[string columnName]
        {
            get {

                switch (columnName)
                {
                    case "SelectedName":
                        {
                            if (SelectedName!=null && ComboboxItems.Count(x => x.ItemName == SelectedName) == 0)
                            {
                                //reset selected value to 0
                                this.SelectedID = 0;
                                return "Invalid selection";

                            }
                            break;
                        }
                }
                return null;
            }
        }
    }
}

結果:

當用戶輸入有效文本(例如item1)時,下面的Textbox顯示SelectedValue的正確ItemId ,並且當用戶輸入無效文本時,所選值將重置為0。

結果

PS:在ComboBox輸入垃圾時,它將始終顯示驗證錯誤指示符(如上所示,為紅色邊框),並且如果將SelectedItem數據綁定到屬性,則它將為null。 因此,如果有錯誤,您就不必關心SelectedValue ,這就是為什么我說我無法在注釋中重現該錯誤。

你真的讓我知道這個,我從來沒有意識到這個問題的存在。 我已經找到了一種解決方案,可以解決您不關心清除組合的問題。 可能有更好的方法,但是我沒有想到。 也許有人在那里有另一個解決方案。

首先,在您的對象中添加對Windows.System.Interactivity的引用,並將其添加到您的XAML中:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

然后,將此代碼添加到組合框:

<ComboBox ItemsSource="{DynamicResource ItemsCompColl}" 
      TextSearch.TextPath="ItemName" x:Name="cbItems"
      SelectedValue="{Binding ItemId, UpdateSourceTrigger=PropertyChanged, 
                              ValidatesOnDataErrors=True}" SelectedValuePath="ItemId"
      Grid.IsSharedSizeScope="True">
      <i:Interaction.Triggers>
         <i:EventTrigger EventName="GotMouseCapture">
             <i:InvokeCommandAction Command="{Binding ClearCombo}" 
               CommandParameter="{Binding ElementName=cbItems}"/>
         </i:EventTrigger>
      </i:Interaction.Triggers>
</ComboBox>

最后,讓我們在ouw View Model中創建命令:

RelayCommand<System.Windows.Controls.ComboBox> _clearCombo;
public ICommand ClearCombo
{
    get
    {
        if (_clearCombo == null)
        {
            _clearCombo = new RelayCommand<System.Windows.Controls.ComboBox>(this.ClearComboCommandExecuted,
            param => this.ClearComboCommandCanExecute());

        }
        return _clearCombo;
    }
}

private bool ClearComboCommandCanExecute()
{
    return true;
}

private void ClearComboCommandExecuted(System.Windows.Controls.ComboBox cb)
{
    cb.Text = "";
}

希望這對您的問題有所幫助。

編輯

好的,在@XAMlMAX注釋之后,我認為他是對的,這可以在Code Behind中輕松完成,並且在MVVM模式中可能更好。 只需向組合框添加一個事件處理程序即可捕獲GotMouseCapture

<ComboBox ItemsSource="{DynamicResource ItemsCompColl}" 
      TextSearch.TextPath="ItemName" x:Name="cbItems"
      SelectedValue="{Binding ItemId, UpdateSourceTrigger=PropertyChanged, 
                              ValidatesOnDataErrors=True}" SelectedValuePath="ItemId"
      Grid.IsSharedSizeScope="True" 
      GotMouseCapture="cbItems_GotMouseCapture" >

然后在視圖后面的代碼中:

private void cbItems_GotMouseCapture(object sender, MouseEventArgs e)
{
   ((ComboBox)sender).Text = "";
}

編輯2

好吧,解決這個問題的最后一個丑陋想法。 我一點都不喜歡它,但是也許它可以解決您的問題。

首先,您必須訂閱TextBoxBase.TextChanged事件:

<ComboBox ItemsSource="{DynamicResource ItemsCompColl}" 
      TextSearch.TextPath="ItemName" x:Name="cbItems"
      SelectedValue="{Binding ItemId, UpdateSourceTrigger=PropertyChanged, 
                              ValidatesOnDataErrors=True}" SelectedValuePath="ItemId"
      Grid.IsSharedSizeScope="True" 
      TextBoxBase.TextChanged="cbItems_TextChanged" >

然后在后面的代碼中添加以下代碼:

private void cbItems_TextChanged(object sender, TextChangedEventArgs e)
{
    string text = ((ComboBox)sender).Text;
   ((YourViewModel)this.DataContext).ItemId= text;
}

這樣,您可以確保ComboBox更改其文本時都會收到通知。 這真的是很糟糕的代碼,但是我已經耗盡了想法……

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM