Динамически добавлять действия 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>

В коде я генерирую несколько списков во время выполнения и хотел бы иметь возможность привязаться к команде relay в режиме просмотра, как в приведенном выше коде xaml, показанном выше ...

Как мне сделать это во время выполнения в коде за представлением.

Кроме того, я хотел бы назначить текст данных для динамически генерируемых списков другим моделям представления, кроме той, которая в настоящее время привязана к моему представлению.

В принципе, у меня есть panaroma, и каждый элемент panaroma создается динамически, причем каждый элемент panaroma имеет список, который будет привязан к модели просмотра с помощью команд реле


person siva    schedule 25.06.2011    source источник
comment
‹ListBox x: Name = ItemGroupsList ItemsSource = {Binding ItemGroups} Height = 496 SelectedItem = {Binding SelectedItemGroup, Mode = TwoWay}› ‹Custom: Interaction.Triggers› ‹Custom: EventTrigger EventName = SelectionChanged› ‹Имя GalaSoft_MvvmLight_Command: EventTo SelectionChangedEvent Command = {Binding GoToEditItemGroupCommand, Mode = OneWay} PassEventArgsToCommand = True / ›‹ / Custom: EventTrigger ›‹ /Custom:Interaction.Triggers ›   -  person siva    schedule 25.06.2011
comment
вам нужно префикс кода с 4 пробелами. И что мы говорим о Silverlight или WPF?   -  person AxelEckenberger    schedule 25.06.2011
comment
Это приложение wp7 silverlight 3. Извините, я должен был упомянуть это раньше   -  person siva    schedule 26.06.2011


Ответы (1)


Примечание. См. также связанных опубликовать.

В этой статье описывается, как можно привязать поведения из исходного кода.

Однако я твердо не советовал бы вам идти по этому пути, если у вас нет веской необходимости в этом. Если вы используете этот подход в своем ViewModel, вы потеряете всякую тестируемость, поскольку он генерирует ViewModel, который сильно связан с View и фактически не может жить без него. (Дополнительное примечание: по этой причине также не рекомендуется возвращать аргументы событий в ViewModel, используйте CommandParameter вместо того, чтобы возвращать DataContext, если необходимо).

Обычно вы можете архивировать свою цель с помощью MVVM другим способом, и остальная часть сообщения описывает это.

Во-первых, вам не нужно использовать Command для получения выбранного свойства или для получения уведомления об изменении этого свойства. Обычный шаблон для этого состоит в том, что вы привязываете SelectedItem вашего списка к свойству в вашем ViewModel. Теперь вы можете использовать событие PropertyChanged, чтобы отслеживать изменение этого свойства.

Во-вторых, используйте шаблоны для создания и стилизации ваших списков. Если вам нужно показать их только при выборе элемента, используйте BooleanToVisibility (Образец см. Здесь converter и привяжите свойство Visibility подсписок к свойству на вашем ViewModel с помощью конвертера (не в моем примере).

В примере создается ListBox, ItemsSource которого привязан к свойству Items объекта ViewModel. Далее он создает ContentControl, DataContext которого привязан к SelectedItem ViewModel. Затем ContentControl снова содержит ListBox, где DataContext привязан к свойству SubItem ItemViewModel. MainViewModel генерирует тестовые данные для отображения во время разработки и выполнения.

В остальной части поста показан образец:

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 [Имя]

    /// <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 можно найти здесь .

person AxelEckenberger    schedule 25.06.2011
comment
Спасибо за идею .. У меня еще вопросы. У меня есть один элемент panaroma в wp7, для которого данные привязаны к элементу дизайна. Остальные элементы panaroma создаются во время выполнения и привязаны к просмотру моделей во время выполнения .. Я хотел бы сделать это чисто во время разработки декларативно в xaml .. - person siva; 28.06.2011
comment
Как определить шаблон данных для элемента панорамы и установить контекст данных для этих элементов панорамы в мою коллекцию моделей представления во время выполнения. Этот код не работает для каждого (группа Model.LocationGroup в viewModel.LocationGroups) {if (group.TotalItems ›0) {PanoramaItem pi = new PanoramaItem (); pi.Header = group.Name; pi.Orientation = System.Windows.Controls.Orientation.Horizontal; ItemLocationListViewModel itemLocationViewModel = viewModel [group.LocationGro - person siva; 28.06.2011