2009-09-17 64 views
0

这是一个很长的。我添加了代码,以便您可以看到我正在尝试执行的操作。让我知道是否有什么不明确使用ViewModel WPF嵌套列表框数据绑定

我想从多层模式中的嵌套列表框中选择项目。这里是代码(去除很多不需要的东西)

public class Item 
{ 
    public string Name { get; set; } 

    public IList<Item> SubItems { get; set; } // 

    public bool IsSelected { get; set; } 
} 
//Chicken Fried Chicken 
//A hearty boneless chicken breast, lightly breaded in our special seasonings and 
//golden fried. Served with garlic mashed potatoes, country gravy and seasonal vegetables 
// from Applebees 

//Item - Chicken Fried Chicken 
//SubItem- mashed potatoes 
//SubItem- country gravy 
//SubItem- seasonal vegetables 
//SubItem- Fries 
//SubItem- Sauted vegetables 
//SubItem- House Salad 

public class ItemViewModel : INotifyPropertyChanged, IItemViewModel 
{ 


    ObservableCollection<Item> selectedData = new ObservableCollection<Item>(); 

    private ObservableCollection<Item> todaysItems; 
    public ObservableCollection<Item> TodaysItems 
    { 
     get { return todaysItems; } 
     private set 
     { 
      if (todaysItems != value) 
      { 
       todaysItems = value; 
       PropertyChanged(this, new PropertyChangedEventArgs("todaysItems")); 
      } 
     } 
    } 



    public ItemViewModel(IItemView itemView) 
    { 
     this.View = itemView; 
     this.View.Model = this; 

     List<Item> items = service.GetAllTestItems(); 
     TodaysItems = new ObservableCollection<Item>(items); 

     selectedData.CollectionChanged += (sender, e) => UpdateSummary(); 
    } 



    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
    private void NotifyPropertyChanged(string propertyName) 
    { 
     var handler = this.PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    #endregion 


    // How to get Selected Items from ListBox 

    public ObservableCollection<Item> SelectedData 
    { 
     get { return selectedData; } 
     set 
     { 
      selectedData = value; 
     } 
    } 


    private void UpdateSummary() 
    { 
     // here I can get selected data , I can find which Item is selected and then update its SubItems IsSelected (CLR) Property 
     // but something is not right here 
    } 
} 

XAML

<UserControl x:Class="ItemView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:prism="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation" 
      xmlns:ZCom="clr-namespace:MyProj.Infrastructure;assembly=Infrastructure"> 

    <Grid > 
     <ListBox ItemsSource="{Binding TodaysItems}"> 
      <ListBox.ItemTemplate> 
       <DataTemplate > 
        <Border BorderThickness="1,1,1,1" CornerRadius="2,2,2,2" BorderBrush="Black"> 
         <Grid MinHeight="50" Width="150" Height="Auto" Margin="0,0,0,0"> 
          <Grid.RowDefinitions> 
           <RowDefinition /> 
           <RowDefinition/> 
           <RowDefinition /> 
          </Grid.RowDefinitions> 
          <Grid.ColumnDefinitions> 
           <ColumnDefinition Width="150"/> 
           <ColumnDefinition Width="0"/> 
          </Grid.ColumnDefinitions> 
          <TextBlock Margin="4,4,2,2" Grid.Row="0" Width="Auto" TextWrapping="Wrap" Text="{Binding Path=Name}" /> 
          <Grid Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" > 
           <Grid.Style> 
            <Style> 
             <Style.Triggers> 
              <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource= 
                    {RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}} 
              }" Value="false"> 
               <Setter Property="Grid.Visibility" Value="Collapsed"/> 
              </DataTrigger> 
             </Style.Triggers> 
            </Style> 
           </Grid.Style> 
           <Grid.RowDefinitions> 
            <RowDefinition Height="35"/> 
            <RowDefinition Height="*"/> 
           </Grid.RowDefinitions> 
           <TextBlock Margin="2,4,2,2" Grid.Row="0" Width="Auto" FontSize="10" FontStyle="Italic" TextWrapping="Wrap" Text="{Binding Path=Note}"/> 

           <ListBox Style="{DynamicResource MyStyle}" Grid.Row="1" ItemsSource="{Binding Path=Modifiers}" SelectionMode="Multiple" 
             ZCom:ListBoxHelper.SelectedItems="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.SelectedData}"> 
            <ListBox.ItemTemplate> 
             <DataTemplate > 
              <TextBlock Margin="2,2,2,2" TextWrapping="Wrap" Text="{Binding Path=Name}" /> 
             </DataTemplate> 

            </ListBox.ItemTemplate> 
           </ListBox> 
          </Grid> 

         </Grid> 
        </Border> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
    </Grid> 
</UserControl> 

我使用ListBoxHelper(基础设施)从 http://marlongrech.wordpress.com/2009/06/02/sync-multi-select-listbox-with-viewmodel/

我得到项目和子项目的看法。

1)什么是更好的方式来设置子项的IsSelected属性从嵌套列表框

我会添加将存储所选的项目数据库,一旦双击了一个命令。子项将根据其IsSelected值存储为子记录。

2)有没有办法让c#类的可见子类SubItems属性。我不想通过将Observable添加到对象中来更改它,因为它将在另一个程序集中并可能被其他应用程序使用。

编辑1: 发现有点用的问题

WPF Databinding to composite class patterns

但同样为了这个,我将不得不从INotifyPropertyChanged的继承。

编辑2: 让我看看我能不能解释一下更好 - ListBox1的单人选择模式和家长&列表框2是多选。 ListBox1绑定(项目源)到返回observablecollection的属性。 ListBox2绑定到Item类(Item.SubItems)中的一个Property返回IList。 Item类具有IsSelected Property.I希望能够选择应将SubItems的IsSelected Property设置为true的子项。知道Item类中没有INotifyPropertyChanged继承,我该如何实现这一点。我假设,除非子项目有一些可观察的集合,否则任何更改都不会通知源代码。使用selectedData属性,我可以通过查找父项来更新子项,但随后更新视图,我必须为涉及所有项目和子项目的“项目”设置firePropertChanged。我只想通过绑定机制来通知子项更改。对不起,如果我还不清楚。

编辑3:

我想没有办法,只能在项目类执行INotifyPropertyChanged。其他的方法是实现一个视图模型,它非常专注于视图的需求,但是这会增加很多代码。

回答

0

这是一个有点混淆你的总体目标是什么。

如果你只是试图从一个嵌套列表框中选择项目,你是否试过给你的列表框x:Name并通过你的UserControl(ItemView)类中的属性公开SelectedItems?

public IList SelectedItems 
{ 
    get { return nestedListBox.SelectedItems; } 
} 
+0

@ Guard-请参阅编辑2.我试图写它作为评论,但它变得太长 – TheMar 2009-09-17 20:54:32