动态将eventtocommand操作添加到列表框 [英] Dynamically add eventtocommand actions to a listbox

查看:113
本文介绍了动态将eventtocommand操作添加到列表框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的页面上有

命名空间:

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>

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

In the code, I am generating multiple listboxes at run time and would like to be able to bind to a relaycommand on the viewmode like the above xaml code shown above...

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

How do I do the above at run time in the code behind of the view.

此外,我想将动态生成的列表框的数据上下文分配给与当前绑定到我的视图的视图模型不同的视图模型.

Also, I would like to assign the datacontext for the dynamically generated listboxes to different view models than the one currently bound to my view.

基本上,我有一个全景图像,每个全景图像项目都是动态创建的,每个全景图像项目都有一个列表框,该列表框将通过中继命令绑定到视图模型

Basically, I have a panaroma and with each panaroma items being created dynamically with each panaroma item having a listbox that will be bound to a viewmodel with relaycommands

推荐答案

注意:另请参见

Note: See also related post.

本文介绍了如何从后面的代码中附加行为.

This article describes how you can attach behaviours from code behind.

但是,除非您有令人信服的需求,否则我强烈建议您不要走这条路.如果在ViewModel中使用此方法,则会失去所有可测试性,因为它会生成与View高度耦合的ViewModel,实际上没有它就无法生存. (<旁注:出于这个原因,如果需要,将事件args返回给ViewModel并使用CommandParameter代替返回DataContext也不是一个好习惯.)

However, I firmly would not advise you to go down this route unless you have a compelling need to do so. If you use this approach in your ViewModel, you will loose all testability as it generates a ViewModel that is highly coupled to the View, and in fact cannot live without it. (Side note: for this reason it is also not good practise to return the event args to the ViewModel use CommandParameter instead to return the DataContext if needed).

通常,您可以以其他方式使用MVVM归档目标,其余内容将对此进行介绍.

Normally you can archive your goal using MVVM in another manner, and the rest of the post describes this.

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

First, you do not need to use a Command to get the selected property, nor to get the notification that this property has changed. The usual pattern for this is that you bind the SelectedItem of your list box to a property in your ViewModel. Now you can use the PropertyChanged event to track when this property changed.

第二,使用模板来生成和设置列表框的样式.当您只需要在选中该项目时才显示它们时,请使用BooleanToVisibility(示例请参阅转换器,然后使用转换器(而不是我的示例)将子列表框的Visibility属性绑定到ViewModel上的属性.

Second, use templates to generate and style your listboxes. When you need to only show them when the item is selected use a BooleanToVisibility (Sample see here converter and bind the sub-listboxes' Visibility property to a property on your ViewModel using the converter (not my the sample).

该示例创建一个列表框,该列表框的ItemsSource绑定到ViewModel的Items属性.它还创建一个ContentControl,该ContentControlDataContext绑定到ViewModelSelectedItem.然后,ContentControl再次包含ListBox,其中DataContext绑定到ItemViewModelSubItem属性. MainViewModel生成要在设计时和运行时显示的测试数据.

The sample creates a ListBox that has its ItemsSource bound to the Items property of the ViewModel. It further creates a ContentControl that has its DataContext bound to the SelectedItem of the ViewModel. The ContentControl then contains again a ListBox where the DataContext is bound to the SubItem property of the ItemViewModel. The MainViewModel generates test data to be shown at design time and run time.

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

The rest of the post shows an sample:

1.主页的XAML(除外):

        <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
}

3. ItemView模型

公共类ItemViewModel:ViewModelBase { #region [名称]

public class ItemViewModel : ViewModelBase { #region [Name]

    /// <summary>
    /// The <see cref="Name" /> property's name.
    /// </summary>
    public const string NamePropertyName = "Name";

    private string _name = default(string);

    /// <summary>
    /// Gets the Name 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 string Name {
        get {
            return _name;
        }

        set {
            if (_name == value) {
                return;
            }

            var oldValue = _name;
            _name = value;

            // Update bindings, no broadcast
            RaisePropertyChanged(NamePropertyName);

            // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
            //RaisePropertyChanged(NamePropertyName, oldValue, value, true);
        }
    }

    #endregion

    #region [SubItems]

    /// <summary>
    /// The <see cref="SubItems" /> property's name.
    /// </summary>
    public const string SubItemsPropertyName = "SubItems";

    private ObservableCollection<ItemViewModel> _myProperty = new ObservableCollection<ItemViewModel>();

    /// <summary>
    /// Gets the SubItems 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> SubItems {
        get {
            return _myProperty;
        }

        set {
            if (_myProperty == value) {
                return;
            }

            var oldValue = _myProperty;
            _myProperty = value;

            // Update bindings, no broadcast
            RaisePropertyChanged(SubItemsPropertyName);

            // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
            //RaisePropertyChanged(SubItemsPropertyName, oldValue, value, true);
        }
    }

    #endregion
}

编辑2

可以找到Panorama控件的模板 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆