我有一个下拉列表(ComboBox
),显示计算机上可用的所有COM端口。现在,当您连接和断开设备时,端口会进出。
出于性能原因,我不想继续拨打System.IO.Ports.SerialPort.GetPortNames()
,而只是在用户点击Combobox时调用它?这可能吗?是否存在针对此问题的MVVM方法?
答案 0 :(得分:8)
使用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>
编辑:显然DropDownOpened不是SelectionChanged,正如Patrice评论的那样。
答案 1 :(得分:0)
您可以使用类似MVVMLight的EventToCommand来完成此任务。基本上,单击组合的事件将挂钩到您的MVVM命令绑定,然后它将触发调用GetPortNames()的方法。
以下是一些替代方案:
MVVM Light: Adding EventToCommand in XAML without Blend, easier way or snippet?(查看接受的答案)
http://www.danharman.net/2011/08/05/binding-wpf-events-to-mvvm-viewmodel-commands/(棱镜)
答案 2 :(得分:0)
我建议删除“仅限点击更新”的想法,并为此使用绑定和通知(除非出于某种原因,您认为会有如此多的连接/断开事件,这会降低您的系统速度)。最简单的版本是依赖属性。
在ViewModel上提供IObservableList<Port>
属性作为依赖项属性,如下所示:
/// <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>));
现在,无论何时连接或断开设备,都可以在该列表中添加/删除项目,只是不要替换列表。这将强制列表为列表中的每个操作发送ListChangedEvent
,并且ComboBox(或任何其他绑定的UI)将对这些事件做出反应。
这对你来说应该足够高效,因为这只会导致UI ComboBox在事件发生时更新。
答案 3 :(得分:0)
我尝试将事件路由到命令:
XAML:
<ComboBox
ItemsSource="{Binding Items}"
local:ControlBehavior.Event="SelectionChanged"
local:ControlBehavior.Command="{Binding Update}" />
代码:
using System;
using System.Reflection;
using System.Windows;
using System.Windows.Input;
namespace StackOverflow
{
public class ControlBehavior
{
public static DependencyProperty CommandParameterProperty = DependencyProperty.RegisterAttached("CommandParameter", typeof(object), typeof(ControlBehavior));
public static DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(ControlBehavior));
public static DependencyProperty EventProperty = DependencyProperty.RegisterAttached("Event", typeof(string), typeof(ControlBehavior), new PropertyMetadata(PropertyChangedCallback));
public static void EventHandler(object sender, EventArgs e)
{
var s = (sender as DependencyObject);
if (s != null)
{
var c = (ICommand)s.GetValue(CommandProperty);
var p = s.GetValue(CommandParameterProperty);
if (c != null && c.CanExecute(s))
c.Execute(s);
}
}
public static void PropertyChangedCallback(DependencyObject o, DependencyPropertyChangedEventArgs a)
{
if (a.Property == EventProperty)
{
EventInfo ev = o.GetType().GetEvent((string)a.NewValue);
if (ev != null)
{
var del = Delegate.CreateDelegate(ev.EventHandlerType, typeof(ControlBehavior).GetMethod("EventHandler"));
ev.AddEventHandler(o, del);
}
}
}
public string GetEvent(UIElement element)
{
return (string)element.GetValue(EventProperty);
}
public static void SetEvent(UIElement element, string value)
{
element.SetValue(EventProperty, value);
}
public ICommand GetCommand(UIElement element)
{
return (ICommand)element.GetValue(CommandProperty);
}
public static void SetCommand(UIElement element, ICommand value)
{
element.SetValue(CommandProperty, value);
}
public object GetCommandParameter(UIElement element)
{
return element.GetValue(CommandParameterProperty);
}
public static void SetCommandParameter(UIElement element, object value)
{
element.SetValue(CommandParameterProperty, value);
}
}
}