2013-04-02 3 views
0

Моя проблема: У меня есть список с владельцами собак, и у меня есть список с собаками. Я хочу изменить элемент списка элементов для собак следующим образом: DogName (textblock) + DogKind (textblock) + Owners (combobox). Первые два были успешными, но я не могу добавить существующих владельцев в combobox. Если я дать имя моего выпадающий список, как:добавление элементов в combobox из списка

<ComboBox x:Name="mycombo" /> 

я не могу видеть переменную mycombo в C# код. Часть XAML:

<Window x:Class="CodeFirst.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:sajat="clr-namespace:CodeFirst" 
     Title="MainWindow" Height="557.638" Width="721.294" 
     > 
<Grid x:Name="grid1"> 
<ListBox x:Name="listbox2" HorizontalAlignment="Left" Height="313" Margin="338,10,0,0" VerticalAlignment="Top" Width="250"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <StackPanel Orientation="Horizontal">       
         <TextBlock Text="{Binding Path=Name}"/> 
         <TextBlock Text=", "/> 
         <TextBlock Text="{Binding Path=Kind}"/>  
         <ComboBox /> 
        </StackPanel> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
</ListBox>  
</Grid> 
</Window> 

Как я могу дать ItemSource на выпадающий список, или как я могу достичь, чтобы добавить владельцев?

+0

Рассмотрите возможность использования конвертера, не используйте 3 текстовых поля, используйте только 1 и измените текст единственного текстового блока с форматированной строкой или получите его с помощью конвертера. – David

ответ

0

Если вы используете DataContext, вы можете установить Binding так:

<ComboBox ItemsSource="{Binding Path=DataContext.MyItemsSource, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"></ComboBox> 
0

Прежде всего, для того, чтобы работать с WPF или другими XAML на основе технологий, вы должны понимать, что

UI is not Data. Data is Data. UI is UI.

Это означает, что вы не должны манипулировать любые ComboBox или любые другие элементы пользовательского интерфейса в коде, для того, чтобы заполнить их с данными, но вместо того, чтобы создать ViewModel и связать эти объекты с этим.

В этом примере Window сам используются как ViewModel, потому что это простой пример, но вы должны рассмотреть вопрос о переходе всей логики приложения в отдельный класс:

<Window x:Class="MiscSamples.UIisNotData" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="UIisNotData" Height="300" Width="300"> 
    <UniformGrid Rows="1" Columns="2"> 
     <DockPanel> 
      <TextBlock Text="Owners:" DockPanel.Dock="Top" FontWeight="Bold" TextAlignment="Center" Margin="2"/> 
      <Button Content="Add" Width="80" DockPanel.Dock="Bottom" Margin="2" Click="AddOwner"/> 

      <ListBox ItemsSource="{Binding Owners}"> 
       <ListBox.ItemTemplate> 
        <DataTemplate> 
         <Grid> 
          <TextBlock Text="{Binding Name}" x:Name="block"/> 
          <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Visibility="Collapsed" x:Name="box"/> 
         </Grid> 
         <DataTemplate.Triggers> 
          <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBoxItem}}" Value="True"> 
           <Setter TargetName="block" Property="Visibility" Value="Collapsed"/> 
           <Setter TargetName="box" Property="Visibility" Value="Visible"/> 
          </DataTrigger> 
         </DataTemplate.Triggers> 
        </DataTemplate> 
       </ListBox.ItemTemplate> 
      </ListBox> 
     </DockPanel> 

     <DockPanel> 
      <TextBlock Text="Dogs:" DockPanel.Dock="Top" FontWeight="Bold" TextAlignment="Center" Margin="2"/> 
      <ListBox ItemsSource="{Binding Dogs}" HorizontalContentAlignment="Stretch"> 
       <ListBox.ItemTemplate> 
        <DataTemplate> 
         <DockPanel> 
          <ComboBox ItemsSource="{Binding DataContext.Owners, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" 
             SelectedItem="{Binding Owner}" DisplayMemberPath="Name" 
             DockPanel.Dock="Right" Width="100"/> 
          <TextBlock> 
           <Run Text="{Binding Name}"/> 
           <Run Text=", "/> 
           <Run Text="{Binding Kind}"/> 
          </TextBlock> 
         </DockPanel> 
        </DataTemplate> 
       </ListBox.ItemTemplate> 
      </ListBox> 
     </DockPanel> 
    </UniformGrid> 
</Window> 

Код За (Этот код должен быть размещен в ViewModel):

public partial class UIisNotData : Window 
    { 
     public ObservableCollection<Owner> Owners { get; set; } 
     public ObservableCollection<string> Kinds { get; set; } 
     public ObservableCollection<Dog> Dogs { get; set; } 

     public UIisNotData() 
     { 
      InitializeComponent(); 

      Owners = new ObservableCollection<Owner> 
       { 
        new Owner() {Name = "Jack"}, 
        new Owner() {Name = "Mike"}, 
        new Owner() {Name = "Kirk"}, 
        new Owner() {Name = "John"}, 
       }; 

      Kinds = new ObservableCollection<string> 
       { 
        "Affenpinscher", 
        "Afghan Hound", 
        "Airedale Terrier", 
        "Akita" 
        //.. All the rest of dog Breeds taken from http://www.petmd.com/dog/breeds?breed_list=az#.UVsQKpPcmQo 
       }; 

      Dogs = new ObservableCollection<Dog> 
       { 
        new Dog() {Name = "Bobby", Kind = Kinds[0], Owner = Owners[0]}, 
        new Dog() {Name = "Fido", Kind = Kinds[1], Owner = Owners[1]}, 
        new Dog() {Name = "Toby", Kind = Kinds[2], Owner = Owners[2]} 
       }; 

      DataContext = this; 
     } 

     private void AddOwner(object sender, RoutedEventArgs e) 
     { 
      Owners.Add(new Owner(){Name = "New Owner"}); 
     } 
    } 

модели данных:

public class Owner : PropertyChangedBase 
    { 
     private string _name; 
     public string Name 
     { 
      get { return _name; } 
      set 
      { 
       _name = value; 
       OnPropertyChanged("Name"); 
      } 
     } 
    } 

    public class Dog: PropertyChangedBase 
    { 
     private string _name; 
     public string Name 
     { 
      get { return _name; } 
      set 
      { 
       _name = value; 
       OnPropertyChanged("Name"); 
      } 
     } 

     private Owner _owner; 
     public Owner Owner 
     { 
      get { return _owner; } 
      set 
      { 
       _owner = value; 
       OnPropertyChanged("Owner"); 
      } 
     } 

     private string _kind; 
     public string Kind 
     { 
      get { return _kind; } 
      set 
      { 
       _kind = value; 
       OnPropertyChanged("Kind"); 
      } 
     } 
    } 

PropertyChangedBase Класс:

public class PropertyChangedBase:INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

Результат:

enter image description here

Есть 3 важные аспекты, которые необходимо учитывать об этом примере:

  • Я нахожусь в никоим образом не манипулирует UI elem в коде. Это совершенно ненужно большую часть времени в WPF.
  • Классы из инструмента модели данных INotifyPropertyChanged для поддержки двухсторонней привязки в WPF.
  • Коллекции имеют тип ObservableCollection<T>, чтобы поддерживать автоматическое уведомление при добавлении/удалении элементов из коллекции (для автоматического обновления ListBoxes и т. Д.).

Другое, что вы можете заметить, это то, что элементы XAML в моем примере не имеют определенного размера или значений Margin.Такие вещи, как Margin="338,10,0,0", как правило, вы получаете от дизайнера Visual Studio и указывают на плохо структурированный макет. Я рекомендую вам взглянуть на элементы Layout в WPF (DockPanel, StackPanel, Grid, UniformGrid, WrapPanel и т. Д.) И начать кодирование XAML самостоятельно, вместо использования конструктора. Это позволит значительно повысить уровень масштабируемости и избавит вас от нюансов элементов фиксированной позиции.

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