如何同步两个列表?

时间:2014-11-18 20:41:50

标签: c# wpf data-binding combobox listbox

我有一个ListBox中显示的Label对象列表。可以为标签分配可以从ComboBox中选择的字体。 Label对象通过FontId引用Font对象。

从ListBox中选择Label时,应在ComboBox中选择相应的Font对象。但是,从ComboBox中选择字体应将字体“分配”到所选标签,而不在ListBox中选择匹配项。这就是我称之为'单向'同步的原因。

我当前的代码在两个方向同步两个列表,即从ComboBox中选择一个Font对象导致在ListBox中选择带有相应字体id的Label。

下面你会找到带有Label和Font模型以及XAML的ViewModel。

using System.Collections.Generic;
using System.ComponentModel;

namespace WpfApplication1
{
    public class NotifyPropertyChanged : System.ComponentModel.INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string prop)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
            }
        }
    }

    public class ViewModel : NotifyPropertyChanged
    {
        public class Label : NotifyPropertyChanged
        {
            public Label(string name, int id)
            {
                this.name = name;
                this.fontId = id;
            }

            string name;
            public string Name 
            {
                get { return name; }
                set
                {
                    if (name == value) return;
                    name = value;
                    RaisePropertyChanged("Name");
                }
            }

            int fontId;
            public int FontId
            {
                get { return fontId; }
                set
                {
                    if (fontId == value) return;
                    fontId = value;
                    RaisePropertyChanged("FontId");
                }
            }
        }

        public class Font : NotifyPropertyChanged
        {
            public Font(string face, int id)
            {
                this.face = face;
                this.id = id;
            }

            int id;
            public int Id
            {
                get { return id; }
                set
                {
                    if (id == value) return;
                    id = value;
                    RaisePropertyChanged("Id");
                }
            }

            string face;
            public string Face
            {
                get { return face; }
                set
                {
                    if (face == value) return;
                    face = value;
                    RaisePropertyChanged("Face");
                }
            }
        }

        List<Label> labels = new List<Label>
        {
            new Label("City", 1),
            new Label("Road", 13),
            new Label("POI", 17),
            new Label("Favorite", 42)
        };

        public IEnumerable<Label> Labels
        {
            get { return labels; }
        }

        List<Font> fonts = new List<Font>
        {
            new Font("Arial 20", 1),
            new Font("Arial 10", 13),
            new Font("Arial 8", 17),
            new Font("Arial 12", 42),
            new Font("Times 12", 47),
            new Font("Times 18", 11)
        };

        public IEnumerable<Font> Fonts
        {
            get { return fonts; }
        }

        Label curLabel;
        public Label CurrentLabel
        {
            get { return curLabel; }
            set
            {
                if (curLabel == value) return;
                curLabel = value;
                RaisePropertyChanged("CurrentLabel");
            }
        }

        Font curFont;
        public Font CurrentFont
        {
            get { return curFont; }
            set
            {
                if (curFont == value) return;
                curFont = value;
                RaisePropertyChanged("CurrentFont");
            }
        }
    }
}

这里是XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="216" ResizeMode="NoResize" SizeToContent="Width">
    <WrapPanel Margin="10">
        <ListBox Name="labelListBox" Width="160" Height="130" Margin="10"
                 ItemsSource="{Binding Labels}"
                 DisplayMemberPath="Name"
                 SelectedItem="{Binding CurrentLabel}"
                 SelectedValuePath="FontId"/>

        <ComboBox Name="fontComboBox" Width="160" Height="30" Margin="10" VerticalAlignment="Top"
                  ItemsSource="{Binding Fonts}"
                  DisplayMemberPath="Face"
                  SelectedValuePath="Id"
                  SelectedValue="{Binding ElementName=labelListBox, Path=SelectedValue}"/>
    </WrapPanel>
</Window>

代码隐藏: 使用System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }
    }
}

感谢提示!

2 个答案:

答案 0 :(得分:1)

简单的解决方案是将绑定的Mode(在ComboBox中)设置为OneWay

<ComboBox Name="fontComboBox" Width="160" Height="30" Margin="10" 
          VerticalAlignment="Top"
          ItemsSource="{Binding Fonts}"
          DisplayMemberPath="Face"
          SelectedValuePath="Id"
          SelectedValue="{Binding ElementName=labelListBox, Path=SelectedValue,
                                  Mode=OneWay}"/>

现在在ListBox中选择时,它的SelectedValue会发生变化,使ComboBox的SelectedValue发生变化。 SelectedValuePath将实际的SelectedValue解析为Id成员,并将选择匹配的项目。因为我们将绑定模式设置为OneWay,所以从ComboBox中选择项目以及更改ComboBox的SelectedValue不会反映到ListBox的SelectedValue。< / p>

答案 1 :(得分:0)

您的xaml中的小修正如下。希望这是你想要的,它会有所帮助。

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication2"
    Title="MainWindow" Height="216" ResizeMode="NoResize" SizeToContent="Width">
<WrapPanel Margin="10">
    <ListBox Name="labelListBox" Width="160" Height="130" Margin="10"
             ItemsSource="{Binding Labels}"
             DisplayMemberPath="Name"
             SelectedItem="{Binding CurrentLabel}"
             FontSize="{Binding ElementName=fontComboBox , Path=SelectedValue.Id}"
             FontFamily="{Binding ElementName=fontComboBox, Path=SelectedValue.Face}"/>

    <ComboBox Name="fontComboBox" Width="160" Height="30" Margin="10" VerticalAlignment="Top"
              ItemsSource="{Binding Fonts}"                  
              DisplayMemberPath="Face"
              SelectedValue="{Binding CurrentFont}"/>
   </WrapPanel>