多个ItemSsource绑定

时间:2013-11-27 18:52:08

标签: c# wpf binding listbox

我不是很擅长整个MVVM设计模式。虽然我觉得这个项目会从中受益,但请记住,这个项目是从Winforms转换而来的,当时我只是在学习WPF。据说项目的想法是键盘楔和键盘钩。当程序加载时,主窗口变为不可见,系统托盘上的图标允许主窗口再次可见。当主窗口可见时,在其中心有一个列表框,允许分配/定义楔形和热键。仅供参考我将热键称为键盘挂钩监控的按键。所以我要说我正在监控HotKeys F13-F15,我有2个键盘楔块。 Item模板视图很简单。

<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 ...我最终移动到ModelView for 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

1 个答案:

答案 0 :(得分:1)

问题不是(或者自从我帮助过你)这个列表没有在GUI上刷新的事实,事实上你正在创建绑定到UI的ItemsSource的副本,那个副本,并没有做任何事情。

您可以在此处复印:

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

然后在ConfigurationHelper.Configure____(temp.Key)中,您将更改或更新此列表副本。此时,您希望对列表所做的更改在绑定的ItemsSource中生效;但是因为它是副本,所以在更新绑定列表之前不会发生任何事情!

您需要做的就是让ConfigurationHelper.Configure_____(temp.Key)返回更改的项目,然后获取该项目并更新绑定的ViewModel的Keys集合,并通知GUI该集合已更改。< / p>

注意:这个问题的问题在私人电子邮件中得到了彻底解决,但这是我提供的信息,让Robert从右脚开始。