【问题标题】:MVVM Editable ComboBox without changing the SelectedItemMVVM 可编辑组合框,无需更改 SelectedItem
【发布时间】:2020-12-02 22:37:52
【问题描述】:

我和这个用户的要求完全一样:MVVM Editable ComboBox Bindings

我已经尝试了接受的答案:

“将“EditedServerName”之类的属性绑定到 Combobox.Text。当 “EditedServerName”已更改,您可以将值设置为 SelectedServer 的“ServerName”。”

但它不起作用,因为当我尝试拦截“EditedServerName”时,“SelectedServer”为空。我相信这是因为控件尝试在集合中搜索正在编辑的“ServerName”,并且显然无法检索到元素。当我开始编辑并且带有“ServerID”的文本块立即变空时,这一点非常清楚。

XAML:

<ComboBox IsEditable= "True" 
            ItemsSource= "{Binding Servers}"
            DisplayMemberPath= "ServerName"
            SelectedItem="{Binding SelectedServer}"
            Text= "{Binding EditedServerName, UpdateSourceTrigger=LostFocus}" />

<TextBlock Text="{Binding SelectedServer.ServerID}"/>

视图模型:

    public List<Server> Servers { get; set; }
    public Server SelectedServer { get; set; }

    private string editedServerName;
    public string EditedServerName
    {
        get { return editedServerName; }
        set 
        { 
            editedServerName = value;
            SelectedServer.ServerName = value;
        }
    }

    public MainViewModel()
    {
        Servers = new List<Server>();
        Servers.Add(new Server { ServerID = 0, ServerName = "Local" });
        Servers.Add(new Server { ServerID = 1, ServerName = "Remote" });
    }

我知道我可以将“SelectedServer”临时存储在另一个对象上,但如果可能的话,我想要一个更好的周转。

【问题讨论】:

  • 您可以粘贴您的代码以便我们更好地帮助您。
  • @Hayden 我已尽力改善问题。我希望这已经足够清楚了。

标签: c# wpf xaml mvvm .net-core-3.1


【解决方案1】:

有几点:

  1. 您的MainViewModel 没有正确使用INotifyPropertyChanged 接口,建议将其用于将数据绑定回视图。这就是您当前发布的代码对 UI 没有任何更改的原因。

  2. 您说得对,一旦 EditedServerName 更改,SelectedServer 将变为 null,但对于第 1 点,它也达到了这一点。即使我们修复代码以适应数据绑定,SelectedServer 属性也不会处理 null

考虑到这一点,如果我们修改代码以适应上述几点,代码可能如下所示:

以下代码有助于通知视图我们的模型/视图模型的任何更改

public class BaseNotifier : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

这是我们更新后的模型的样子。注意BaseNotifier 中定义的OnPropertyChanged 的使用,因为这将使用新的服务器名称更新视图

public class Server : BaseNotifier
{
    private string _serverName;

    public string ServerName
    {
        get { return _serverName; }
        set
        {
            _serverName = value;
            OnPropertyChanged();
        }
    }

    private int _serverID;

    public int ServerID
    {
        get { return _serverID; }
        set
        {
            _serverID = value;
            OnPropertyChanged();
        }
    }
}

这就是 ViewModel 现在的样子。对于 ViewModel,使用 ObservableCollection 而不是 List 以允许在插入数据时自动更新视图。您还会注意到,代码会检查 SelectedServer 和 EditedServerName 中的 null 是否应该处理您的原始问题。

public class MainViewModel : BaseNotifier
{
    private string editedServerName;
    private Server selectedServer = null;
    public ObservableCollection<Server> Servers { get; set; }
    public Server SelectedServer
    {
        get { return selectedServer; }
        set
        {
            if (value != null)
            {
                selectedServer = value;
                OnPropertyChanged();
            }
        }
    }

    public string EditedServerName
    {
        get { return editedServerName; }
        set
        {
            editedServerName = value;

            if (SelectedServer != null)
            {
                SelectedServer.ServerName = value;
            }

            OnPropertyChanged();
        }
    }

    public MainViewModel()
    {
        Servers = new ObservableCollection<Server>();
        Servers.Add(new Server { ServerID = 0, ServerName = "Local" });
        Servers.Add(new Server { ServerID = 1, ServerName = "Remote" });
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-03
    • 2021-07-27
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多