2014-11-18 3 views
1

У меня есть список объектов Label, представленных в ListBox. Ярлыкам могут быть назначены шрифты, которые могут быть выбраны из ComboBox. Объект Label ссылается на объект Font через FontId.Как синхронизировать два списка в одну сторону?

При выборе ярлыка из списка, соответствующий объект Font должен быть выбран в ComboBox. Однако выбор шрифта из ComboBox «назначает» шрифт выбранной метке без выбора соответствующего элемента в ListBox. Вот почему я назвал эту синхронизацию «oneway».

Мой текущий код синхронизирует два списка в обоих направлениях, то есть выбор объекта Font из результатов ComboBox при выборе метки с соответствующим идентификатором шрифта в ListBox.

Ниже вы найдете ViewModel с моделями меток и шрифтов, а также XAML.

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(); 
     } 
    } 
} 

Спасибо за подсказки!

ответ

1

Простое решение является установка Mode из Binding (в 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 изменится, делая SelectedValue из ComboBox изменение. SelectedValuePath разрешает действительное значение SelectedValue для члена Id и выберет соответствующий элемент. Поскольку мы установили режим привязки на OneWay, выбор элемента из ComboBox, а также изменение SelectedValue ComboBox не отразится на SelectedValue ListBox.

+0

Спасибо, что решает его для моего примера, который я разместил. К сожалению, не в моем проекте - все еще выяснение критической разницы с этим макетом ... – florg

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> 

Смежные вопросы