WPF MVVM - Command binding inside of an ItemsControl

前端 未结 3 476
抹茶落季
抹茶落季 2021-02-03 12:00

I\'m currently converting a small WPF project to MVVM. I have a List in the ViewModel of the main window that my ItemsControl binds to and uses

相关标签:
3条回答
  • 2021-02-03 12:38

    Josh Smith wrote an excellent article in MSDN here where he talks about command binding.

    In your case it boils down to this:

    • 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.

    HTH.

    0 讨论(0)
  • 2021-02-03 12:50

    Do I bind the ItemsControl.ItemsSource to a collection of a new ViewModel class that represents each item?

    Whether you create a CustomObjectViewModel to host the command or place the command within the same ViewModel that has the list really depends on the function of the action occuring. Is it something that belongs with the CustomObject, or is it something that belongs with your current 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)?

    This isn't as bad as it sounds. You don't really need the DataContext of the Window, just the DataContext from before it switched over to the individual items. So if your command was on the same ViewModel that hosts the List of CustomObjects, you could bind to it from within one of the CustomObject's DataTemplate using either of these methods:

    {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.

    For this, I would use something like Attached Command Behaviors which will let you attach a ICommand to any event.

    0 讨论(0)
  • 2021-02-03 13:04

    You can try to keep your Command in your Model.

    public class MyModel
    {
        public MyModel()
        {
            MyCommand = new DelegateCommand(MyCommandExecute);
        }
    
        public ICommand MyCommandCommand { get; set; }
    
        private void MyCommandExecute()
        {
        }
    }
    

    And then, you must have an ObservableList for the list of your Items in your ViewModel as,

    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());
        }
    }
    

    Then in XAML you must say;

    <ItemsControl ItemsSource="{Binding List}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Button Content="MyButton" Command="{Binding MyCommand}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    
    0 讨论(0)
提交回复
热议问题