2013-11-27 42 views
1

我并不擅长整个MVVM设计模式。尽管我觉得这个项目会受益于它,请记住,这个项目是从Winforms转换而来的,并且我当时只是在学习WPF。这就是说该项目的想法是一个键盘楔和键盘钩。当程序加载时,主窗口变得不可见,并且系统托盘上的图标允许主窗口再次变为可见。当主窗口可见时,在其中央有一个列表框,允许分配/定义楔形和热键。仅供参考,我将通过键盘钩子监控的按键称为热键。因此可以说我正在监控HotKeys F13-F15,并且我有2个键盘楔子。项目模板视图非常简单。多个ItemSources绑定

<UserControl x:Class="Keymon.UserControls.HotkeyConfigurationView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <Grid Margin="3,0"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="3*" /> 
      <ColumnDefinition Width="2*" /> 
     </Grid.ColumnDefinitions> 
     <TextBlock Text="{Binding Key}" TextWrapping="Wrap" /> 
     <TextBlock Grid.Column="1" Text="{Binding Path}" HorizontalAlignment="Right" TextWrapping="Wrap" /> 
    </Grid> 
</UserControl> 

或简单地将2个文本块并排绑定到Key和Path。

我做我的热键和KeyboardWedges实现这个

public interface IMyAdvancedListItem 
{ 
    string Key { get; } 
    string Path { get; } 
    string Parameters { get; } 
} 

当我的程序第一次启动时我检查,看看我有什么计算机上,给了我热键和键盘楔子的适当列表。我添加这些正确的名单,然后同时收集值的列表,并摔在IMyAdvancedListItem ......我结束了移动到模型视图为MyAdvancedList

public class MyAdvancedListViewModel 
{ 
    public List<Keymon.ValueTypes.IMyAdvancedListItem> Keys 
    { 
     get 
     { 
      System.Collections.Generic.List<Keymon.ValueTypes.IMyAdvancedListItem> list = new System.Collections.Generic.List<ValueTypes.IMyAdvancedListItem>(); 
      list.AddRange(Globals.MonitoredKeys.Values.Cast<Keymon.ValueTypes.IMyAdvancedListItem>()); 
      list.AddRange(Globals.SerialPortWedges.Values.Cast<Keymon.ValueTypes.IMyAdvancedListItem>()); 
      return list; 
     } 
     set 
     { 
     } 
    } 

    public MyAdvancedListViewModel() 
    { 
    } 

} 

最后当上一个列表框项目的用户双击我有它打开正确的配置对话框,然后更新正确的列表。它更新列表我告诉它刷新后的项目(似乎没有做任何事情)

private void ListBox_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e) 
    { 
     var keyListBox = sender as ListBox; 
     var temp = keyListBox.SelectedItem as Keymon.ValueTypes.IMyAdvancedListItem; 
     var index = keyListBox.SelectedIndex; 

     if (Globals.SerialPortWedges.ContainsKey(temp.Key)) 
     { 
      if (temp.Key == "MSR") 
       ConfigurationHelper.ConfigureWedge(temp.Key); 
      else 
       ConfigurationHelper.ConfigureWedgeEx(temp.Key); 
     } 
     else 
     { 
      ConfigurationHelper.ConfigureHotKey(temp as HotkeyConfiguration); 
     } 
     keyListBox.Items.Refresh(); 
     keyListBox.SelectedIndex = index; 
    } 

现在,你可能会想干脆实行INotifyCollection ..做过一样。我甚至尝试过INotifyProperty。我认为最终这一切都可以归结为我只是猜测我应该做什么,而不理解我真的在做什么。这里仅供参考是来自两个列表的几行重要代码。

public class GlobalHotKeys : INotifyCollectionChanged, INotifyPropertyChanged, IEnumerable 
{ 
    public GlobalHotKeys() 
    { 
    } 
    public HotkeyConfiguration this[int key] 
    { 
     get 
     { 
      return MonitoredKeys[key]; 
     } 
     set 
     { 
      MonitoredKeys[key] = value; 
      NotifyCollectionChanged(NotifyCollectionChangedAction.Replace, value); 
      NotifyPropertyChanged("Keys"); 
     } 
    } 

    private Dictionary<int, HotkeyConfiguration> MonitoredKeys = new Dictionary<int, HotkeyConfiguration>(); 
    public IEnumerable<HotkeyConfiguration> Values { get { return MonitoredKeys.Values; } } 

    #region Notifications 
    private void NotifyCollectionChanged(NotifyCollectionChangedAction action, object affectedObject) 
    { 
     if (CollectionChanged != null) 
     { 
      CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, affectedObject)); 
     } 
    } 
    public event NotifyCollectionChangedEventHandler CollectionChanged; 
    private void NotifyPropertyChanged(string property) 
    { 
     if(PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 

} 

,这里是我的挖起杆

public class GlobalWedges : IEnumerable, INotifyCollectionChanged 
{ 
    public GlobalWedges() 
    { 
     wedges = new Dictionary<string, KeyboardWedgeConfiguration>(); 
    } 
    public KeyboardWedgeConfiguration this[string key] 
    { 
     get 
     { 
      if (wedges.ContainsKey(key)) 
       return wedges[key]; 
      else 
       return null; 
     } 
     set 
     { 
      wedges[key] = value; 
      NotifyCollectionChanged(NotifyCollectionChangedAction.Replace, value); 
     } 
    } 

    private Dictionary<string, KeyboardWedgeConfiguration> wedges; 
    public IEnumerable<KeyboardWedgeConfiguration> Values { get { return wedges.Values; } } 

    #region Notifications 
    private void NotifyCollectionChanged(NotifyCollectionChangedAction action, object affectedObject) 
    { 
     if (CollectionChanged != null) 
     { 
      CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, affectedObject)); 
     } 
    } 
    public event NotifyCollectionChangedEventHandler CollectionChanged; 
    #endregion 

} 

我不应该觉得你需要在上述清单所以这里只是类勾勒出项目的代码。

public class KeyboardWedgeConfiguration : Keymon.ValueTypes.IMyAdvancedListItem, Keymon.ValueTypes.Saveable, IDisposable 
public class HotkeyConfiguration : Keymon.ValueTypes.IMyAdvancedListItem 

对不起,关于所有的代码,但更好有太多不够。哦,我可能忘了。我必须先关闭程序,然后才能看到对热键列表或键盘楔形所做的更改。我知道他们正在更新,因为如果我更新一个密钥来说打开一个计算器,那么它会这样做。任何帮助,为什么?

编辑

只有列表中的这张照片。在此屏幕截图之后,我编辑了F13以打开calc.exe,但列表仍然是这样的。 MyAdvancedList

因此,要显示实际更新,我必须退出我的应用程序,然后重新启动它。这是我希望程序在刷新时做的。 MyAdvancedListAfter

+0

'System.Collections.Generic.List list = new System.Collections.Generic.List ();' - 人类历史上最好的C#代码行。 –

+0

你碰巧有一个gui的样子吗? – Kcvin

+0

@NETscape请参阅编辑。 –

回答

1

这个问题不是因为我帮助过你(或者不是因为我帮助过你),因为这个列表并没有在GUI上刷新,事实上你正在创建一个与ItemsSource绑定的副本用户界面,更改该副本,并无所作为。

在这里你让你的副本:

var temp = keyListBox.SelectedItem as Keymon.ValueTypes.IMyAdvancedListItem; 
var index = keyListBox.SelectedIndex; 

然后在ConfigurationHelper.Configure____(temp.Key)在这里你会改变或更新列表中的这个副本。此时,您期待您对列表所做的更改在绑定的ItemsSource中生效;但是,因为它是一个副本,除非更新绑定列表,否则实际上什么都不会发生!

你需要做的事情就像你的ConfigurationHelper.Configure_____(temp.Key)返回改变的项目,然后采取该项目并更新绑定的ViewModel的集合并通知GUI该集合已经改变。

注意:这个问题的问题在私人电子邮件中完全解决,但是这是我提供的信息,它让罗伯特从右脚开始。