将eventtocommand动作动态添加到列表框

时间:2011-06-25 03:37:06

标签: silverlight windows-phone-7 mvvm-light

我有一个

页面

名称空间:

xmlns:Custom="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
xmlns:GalaSoft_MvvmLight_Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP7" 
设计时

xaml:

<ListBox  x:Name="ItemGroupsList" ItemsSource="{Binding ItemGroups}" Height="496" 
                SelectedItem="{Binding SelectedItemGroup, Mode=TwoWay}" >
    <Custom:Interaction.Triggers>
         <Custom:EventTrigger EventName="SelectionChanged">
             <GalaSoft_MvvmLight_Command:EventToCommand 
                     x:Name="SelectionChangedEvent" 
                     Command="{Binding GoToEditItemGroupCommand, Mode=OneWay}" 
                     PassEventArgsToCommand="True"/>
        </Custom:EventTrigger>
    </Custom:Interaction.Triggers>

在代码中,我在运行时生成多个列表框,并希望能够绑定到viewmode上的relaycommand,如上面显示的上述xaml代码...

如何在运行时在视图后面的代码中执行上述操作。

另外,我想将动态生成的列表框的datacontext分配给不同于当前绑定到视图的视图模型。

基本上,我有一个panaroma,并且动态创建每个panaroma项目,每个panaroma项目都有一个列表框,该列表框将绑定到具有relaycommands的viewmodel

1 个答案:

答案 0 :(得分:1)

注意:另请参阅related post

This article描述了如何从代码中附加行为。

然而,除非您有引人注目的需要,否则我坚决不建议您沿着这条路走下去。如果您在ViewModel中使用此方法,则会失去所有可测试性,因为它会生成与ViewModel高度耦合的View,实际上如果没有它就无法生存。 (旁注:因此,将事件参数返回到ViewModel使用CommandParameter而不是在需要时返回DataContext也不是一种好习惯。

通常你可以用另一种方式使用MVVM归档你的目标,其余的帖子描述了这一点。

首先,您不需要使用Command来获取所选属性,也不需要获取此属性已更改的通知。通常的模式是将列表框的SelectedItem绑定到ViewModel中的属性。现在,您可以使用PropertyChanged事件来跟踪此属性何时更改。

其次,使用模板生成列表框并设置样式。如果您只需在选择项目时显示它们,请使用BooleanToVisibilitySample see here转换器并将子列表框'Visibility属性绑定到ViewModel上的属性转换器(不是我的样本)。

该示例创建一个ListBox,其ItemsSource绑定到ViewModel的Items属性。它进一步创建ContentControl,其DataContextSelectedItem的{​​{1}}绑定。然后,ViewModel再次包含ContentControl,其中ListBox绑定到DataContext的{​​{1}}属性。 SubItem生成要在设计时和运行时显示的测试数据。

帖子的其余部分显示了一个示例:

<强> 1。主页的XAML(除外):

                                                                                                                                                                                                                                                                                                                                                                                       

ItemViewModel

<强> 2。主视图模型

MainViewModel

第3。 ItemView模型

public class ItemViewModel:ViewModelBase     {         #region [姓名]

        <ContentControl x:Name="target1" Grid.Row="1" DataContext="{Binding SelectedItem}" Margin="20,0">
            <ContentControl.Template>
                <ControlTemplate>
                    <StackPanel>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="Name:" Margin="0,0,10,0"/>
                            <TextBlock Text="{Binding Name}"/>
                        </StackPanel>
                        <ListBox ItemsSource="{Binding SubItems}">
                            <ListBox.ItemContainerStyle>
                                <Style TargetType="ListBoxItem">
                                    <Setter Property="Padding" Value="1"/>
                                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                                </Style>
                            </ListBox.ItemContainerStyle>
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <Border Background="navy" BorderBrush="White" BorderThickness="1">
                                        <TextBlock Text="{Binding Name}"/>
                                    </Border>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                    </StackPanel>
                </ControlTemplate>
            </ContentControl.Template>
        </ContentControl>
    </Grid>
</Grid>

修改2

可以找到 public MainViewModel() { // working with fields to ensure no events are fired during initial phase this._items = new ObservableCollection<ItemViewModel>(); for (int i = 0; i < 5; ++i) { var item = new ItemViewModel() { Name = string.Format("Item {0}", i) }; for (int j = 0; j < 3; ++j) item.SubItems.Add(new ItemViewModel() { Name = string.Format("{0} - Sub Item {1}", item.Name, j) }); this._items.Add(item); } this.SelectedItem = this._items[0]; if (IsInDesignMode) { // Code runs in Blend --> create design time data. } else { // Code runs "for real" } } #region [Items] /// <summary> /// The <see cref="Items" /> property's name. /// </summary> public const string ItemsPropertyName = "Items"; private ObservableCollection<ItemViewModel> _items = default(ObservableCollection<ItemViewModel>); /// <summary> /// Gets the Items property. /// TODO Update documentation: /// Changes to that property's value raise the PropertyChanged event. /// This property's value is broadcasted by the Messenger's default instance when it changes. /// </summary> public ObservableCollection<ItemViewModel> Items { get { return _items; } set { if (_items == value) { return; } var oldValue = _items; _items = value; // Update bindings, no broadcast RaisePropertyChanged(ItemsPropertyName); // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging //RaisePropertyChanged(ItemsPropertyName, oldValue, value, true); } } #endregion #region [SelectedItem] /// <summary> /// The <see cref="SelectedItem" /> property's name. /// </summary> public const string SelectedItemPropertyName = "SelectedItem"; private ItemViewModel _selectedItem = default(ItemViewModel); /// <summary> /// Gets the SelectedItem property. /// TODO Update documentation: /// Changes to that property's value raise the PropertyChanged event. /// This property's value is broadcasted by the Messenger's default instance when it changes. /// </summary> public ItemViewModel SelectedItem { get { return _selectedItem; } set { if (_selectedItem == value) { return; } var oldValue = _selectedItem; _selectedItem = value; // Update bindings, no broadcast RaisePropertyChanged(SelectedItemPropertyName); // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging //RaisePropertyChanged(SelectedItemPropertyName, oldValue, value, true); } } #endregion } 控件的模板here