C# WPF MVVM-单击时更新下拉列表

C# WPF MVVM-单击时更新下拉列表,c#,wpf,drop-down-menu,combobox,C#,Wpf,Drop Down Menu,Combobox,我有一个下拉列表(组合框),显示机器上所有可用的com端口。现在,当您连接和断开设备时,端口来来去去去 出于性能原因,我不想继续调用System.IO.Ports.SerialPort.GetPortNames(),而是在用户单击组合框时调用它?这可能吗?有没有一种MVVM方法可以解决这个问题?您可以使用类似MVVMLight的EventToCommand之类的工具来实现这一点。基本上,单击组合的事件将连接到MVVM命令绑定,然后该绑定将触发调用GetPortNames()的方法 以下是一些备选

我有一个下拉列表(
组合框
),显示机器上所有可用的com端口。现在,当您连接和断开设备时,端口来来去去去


出于性能原因,我不想继续调用
System.IO.Ports.SerialPort.GetPortNames()
,而是在用户单击组合框时调用它?这可能吗?有没有一种MVVM方法可以解决这个问题?

您可以使用类似MVVMLight的EventToCommand之类的工具来实现这一点。基本上,单击组合的事件将连接到MVVM命令绑定,然后该绑定将触发调用GetPortNames()的方法

以下是一些备选方案:

(检查已接受的答案)


(Prism)

我的建议是放弃“点击时仅更新”的想法,只需为此使用绑定和通知(除非出于某种原因,您认为会有太多连接/断开连接事件,这会降低系统的速度)。最简单的版本是依赖属性

在ViewModel上提供一个
IObservableList
属性作为依赖属性,如下所示:

    /// <summary>
    /// Gets or sets...
    /// </summary>
    public IObservableList<Port> Ports
    {
        get { return (IObservableList<Port>)GetValue(PortsProperty); }
        set { SetValue(PortsProperty, value); }
    }

    public static readonly DependencyProperty PortsProperty = DependencyProperty.Register("Ports", typeof(IObservableList<Port>), typeof(MyViewModelClass), new PropertyMetadata(new ObservableList<Port>));
//
///获取或设置。。。
/// 
公共IObservableList端口
{
获取{return(IObservableList)GetValue(PortsProperty);}
set{SetValue(PortsProperty,value);}
}
public static readonly dependencProperty PortsProperty=dependencProperty.Register(“端口”、typeof(IObservableList)、typeof(MyViewModelClass)、new PropertyMetadata(new ObservableList));
现在,无论何时连接或断开设备,您都可以在该列表中添加/删除项目,但不要替换该列表。这将强制列表为列表上的每个操作发送一个
ListChangedEvent
,组合框(或任何其他绑定的UI)将对这些事件做出反应


这对您来说应该足够了,因为这只会导致UI组合框在事件发生时更新。

我尝试将事件路由到命令:

XAML:


使用
InvokeCommandAction

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
DropDownOpenedCommand是ViewModel上的
ICommand
属性

<ComboBox>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="DropDownOpened">
            <i:InvokeCommandAction Command="{Binding DropDownOpenedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ComboBox>


编辑:显然,正如Patrice所评论的,DropdownOpen没有选择更改。

处理
DropdownOpen
事件,并在处理程序中调用
GetPortsNames
,以更新项目。使用MVVM,您可以使用某种
命令执行相同的操作,然后相应地更新ViewModel中的数据。请确保在属性更改时注销事件,以防止内存泄漏。我做了几乎相同的事情,但只是因为InvokeCommandAction不支持传递EventArgs——如果您不需要这样做,我认为InvokeCommandAction要容易得多(参见我的答案)。我喜欢这个--必须出去获取NuGet软件包
System.Windows.Interactivity v4.0 for WPF
,它才能工作。对于在Dot Net Core 3.1中尝试这样做的任何人,快速更新:根据这个答案,System.Windows.Interactivity与Dot Net Core不兼容,但Microsoft.Xaml.Behaviors.WPF提供了所有相同的功能。IMHO,OP关注的性能不是UI更新,而是频繁调用
System.IO.Ports.SerialPort.GetPortNames()
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<ComboBox>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="DropDownOpened">
            <i:InvokeCommandAction Command="{Binding DropDownOpenedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ComboBox>