Вопрос по .net, mvvm, wpf – WPF MVVM - Связывание команд внутри ItemsControl

9

В настоящее время я конвертирую небольшой проект WPF в MVVM. у меня естьList<CustomObject> в ViewModel главного окна, к которому привязывается мой ItemsControl, и использует DataTemplate для построения пользовательского интерфейса каждого элемента. Мой старый код использовал обработчик событий внутри DataTemplate для обработки события щелчка. Я хочу использовать какое-то связывание команд для устранения моих обработчиков событий с выделенным кодом, но DataContext элементов в моем ItemsControl является объектом модели, поэтому я не могу в настоящее время связываться с ICommand из ViewModel.

Таким образом, я полагаю, что есть несколько способов атаковать это, и я не уверен, какой из них будет наиболее "MVVM". способ сделать это. Связывать ли ItemsControl.ItemsSource с коллекцией нового класса ViewModel, который представляет каждый элемент? Или я использую UserControls вместо DataTemplate, и затем я могу привязать каждый UserControl к собственному экземпляру ViewModel, который его представляет? Или есть какое-то выражение для привязки, которое я могу использовать для ссылки на DataContext окна, чтобы иметь доступ к привязке к ViewModel (когда я набираю это, это просто звучит плохо, поэтому я предполагаю, что большое "NO" эта идея)?

Кроме того, я хочу связать свою команду с событием LeftMouseButtonUp элемента управления Grid. Там нет "Команды" для сетки, поэтому я пытался использовать InputBindings. Я мог бы использовать статическую команду (например, одну из встроенных ApplicationCommands), но я не мог использовать выражение привязки для привязки к экземпляру ICommand, который является свойством ViewModel, потому что MouseBinding.Command не является DependencyProperty.

Я довольно запутался в вопросе обработки событий в MVVM, поэтому любая информация ценится.

Ваш Ответ

3   ответа
19

del class that represents each item?

Создаете ли вы CustomObjectViewModel для размещения команды или помещаете команду в тот же ViewModel, у которого есть список, действительно зависит от функции происходящего действия. Это что-то, что принадлежит CustomObject, или это то, что принадлежит вашей текущей ViewModel?

Or is there some kind of binding expression I can use to refer back to the DataContext of the window to have access to bind to the ViewModel (as I type this, it just sounds bad so I'm assuming a big "NO" to this idea)?

Это не так плохо, как кажется. Вы действительно не нуждаетесь в DataContext окна, просто в DataContext до того, как он переключился на отдельные элементы. Поэтому, если ваша команда была в том же ViewModel, в котором размещен список пользовательских объектов, вы можете привязать ее к одному из DataTemplate пользовательского объекта, используя любой из этих методов:

{Binding ElementName=uiCustomObjectsItemsControl, Path=DataContext.MyCommand}
{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.MyCommand}

Also, what I want to bind my command to is the LeftMouseButtonUp event of a Grid control. There's no "Command" for a Grid, so I was attempting to use InputBindings.

Для этого я бы использовал что-то вродеПрикрепленное поведение команд что позволит вам присоединить ICommand к любому событию.

1

public class MyModel
{
    public MyModel()
    {
        MyCommand = new DelegateCommand(MyCommandExecute);
    }

    public ICommand MyCommandCommand { get; set; }

    private void MyCommandExecute()
    {
    }
}

И затем, вы должны иметь ObservableList для списка ваших элементов в вашей ViewModel как,

public class MyViewModel
{
    public MyViewModel()
    {
        MyStarterCommand = new DelegateCommand(MyCommandExecute);

        if (!IsDesignTime)//(bool)DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(DependencyObject)).Metadata.DefaultValue;
            MyCommand.Execute(null);
    }

    private ObservableCollection<MyModel> list;
    private  ICommand MyStarterCommand { get; set; }

    public ObservableCollection<MyModel> List
    {
        get { return list; }
        set
        {
            list = value;
            RaisePropertyChanged(() => List);
        }
    }

    private void MyStarterCommandExecute()
    {
        List = new ObservableCollection<MyModel>();

        //Fill the list here
        List.Add(new MyModel());
    }
}

Тогда в XAML вы должны сказать;

<ItemsControl ItemsSource="{Binding List}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="MyButton" Command="{Binding MyCommand}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
4

Вот где он говорит о привязке команд.

В вашем случае все сводится к следующему:

You won't eliminate ALL of your code-behind, but it will probably look different Your CustomObjects will probably have to have VM shim classes, or be VMs themselves to take advantage of the RelayCommand architecture that he describes.

НТН.

Похожие вопросы