动态地将项目添加到 WPF 组合框,然后在某些事件上重置值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18831926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:39:41  来源:igfitidea点击:

Add items to WPF combobox dynamically and later reset the value on some event

c#wpfxamlcombobox

提问by Saket

I am new to WPF but I searched a lot and in the end decided to seek help from you guys...

我是 WPF 的新手,但我搜索了很多,最后决定向你们寻求帮助......

I have a class - LocationWith primary properties as -

我有一个类 - Location主要属性为 -

LocationName

地点名称

LocationID

位置ID

I wish to bind this class to a combo box in WPF. I fetch the location list from database. I need to display the list in the combobox with the first text / value pair as ---Select One---/ -1. Now, so far I have done this -

我希望将此类绑定到 WPF 中的组合框。我从数据库中获取位置列表。我需要在组合框中显示列表,其中第一个文本/值对为 ---Select One---/ -1。现在,到目前为止我已经做到了 -

create -

创建 -

public ObservableCollection<ComboBoxItem> cbLocationList { get; set; }

cbLocationList = new ObservableCollection<ComboBoxItem>();

SelectedcbDefaultLocationListItem = new ComboBoxItem { Content = "---Select One---" , Tag="-1"};

cbLocationList.Add(SelectedcbDefaultLocationListItem);

Fill the items in a loop as -

将循环中的项目填充为 -

foreach (Location loc in LocationtList)
{

 cbLocationList.Add(new ComboBoxItem  { Content = loc.LocationName, Tag=loc.LocationID.ToString() });

}

where I set the cbLocationListin XAML as -

我在 XAML中将cbLocationList设置为 -

ItemsSource="{Binding cbLocationList}" 

of the combobox. This works well, but on resetting the form I need to reset the value of the combo box to "-1". I am unable to do so with the tag property. (I searched, and it seems we dont have a valueproperty like in the ListItem) Every body seems to suggest I bind it with a class and set the DisplayMemberPath and SelectedValuePath. Now if I directly bind with my Locationclass, How do I insert the --Select One-- item. I could do that by creating a dummy object and insert it into my list before binding. But is this the best way to work in WPF. Maybe there is an altogether different approach which I am missing. Please advise.

的组合框。这很有效,但在重置表单时,我需要将组合框的值重置为“-1”。我无法使用 tag 属性这样做。(我搜索过,似乎我们没有ListItem 中value属性)每个机构似乎都建议我将它与一个类绑定并设置 DisplayMemberPath 和 SelectedValuePath。现在,如果我直接与我的Location类绑定,如何插入 --Select One-- 项目。我可以通过创建一个虚拟对象并在绑定之前将其插入我的列表来做到这一点。但这是在 WPF 中工作的最佳方式吗?也许我缺少一种完全不同的方法。请指教。

Thanks in advance. !

提前致谢。!

回答by TrueEddie

Here is how you would do this with a more MVVM approach:

以下是使用更多 MVVM 方法执行此操作的方法:

ViewModel:

视图模型:

public class MyViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public Location SelectedcbDefaultLocationListItem = new Location { LocationName = "---Select One---", LocationID = -1 };

    public ObservableCollection<Location> LocationList { get; set; }

    private int _selectedLocationID;

    /// <summary>
    /// Get/Set the SelectedLocationID property. Raises property changed event.
    /// </summary>
    public int SelectedLocationID
    {
        get { return _selectedLocationID; }
        set
        {
            if (_selectedLocationID != value)
            {
                _selectedLocationID = value;

                RaisePropertyChanged("SelectedLocationID");
            }
        }
    }        

    /// <summary>
    /// Constructor
    /// </summary>
    public MyViewModel()
    {
        LocationList = new ObservableCollection<Location>();
        LocationList.Add(new Location() { LocationID = 1, LocationName = "Here" });
        LocationList.Add(new Location() { LocationID = 2, LocationName = "There" });

        LocationList.Insert(0, SelectedcbDefaultLocationListItem);

        SelectedLocationID = SelectedcbDefaultLocationListItem.LocationID;
    }

    /// <summary>
    /// Resets the selection to the default item.
    /// </summary>
    public void ResetSelectedItem()
    {
        SelectedLocationID = SelectedcbDefaultLocationListItem.LocationID;
    }

    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }   
}

Code Behind:

背后的代码:

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow
{
    public MyViewModel ViewModel { get; private set; }

    public MainWindow()
    {
        InitializeComponent();

        ViewModel = new MyViewModel();

        DataContext = ViewModel;
    }

    private void ResetButton_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        ViewModel.ResetSelectedItem();
    }
}

XAML:

XAML:

<Window xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"  x:Class="StackOverflow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <ComboBox ItemsSource="{Binding LocationList, Mode=OneWay}" DisplayMemberPath="LocationName" SelectedValuePath="LocationID" SelectedValue="{Binding SelectedLocationID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
            <Button Click="ResetButton_Click" Content="Reset" Margin="5" HorizontalAlignment="Right" />
        </StackPanel>        
    </Grid>    
</Window>

Normally a command would be used instead of calling the reset method in the code behind. But since you aren't using a full MVVM approach this should suffice.

通常会使用命令而不是在后面的代码中调用 reset 方法。但是由于您没有使用完整的 MVVM 方法,这应该就足够了。