Search code examples
mvvmdata-bindinguser-controlsuwptemplate10

UWP UserControl with its own ViewModel as well as Dependency Properties using Template 10


I am creating UWP app using Template 10 and MVVM. My requirement is to create UserControl which will have its own dependency properties as well as has it own ViewModel.

My Requirement:

  1. Call Parent ViewModel command on Button Click.
  2. Bind TexBlock text from UserControl ViewModel

My User Control looks like this:

  <vm:MyUserControl1  AddItem="{Binding MyCommand}"   Component="{Binding}"  RelativePanel.Below="abc" />

User Control XAML:

<StackPanel>
            <TextBlock Text="{x:Bind Component.Text, Mode=OneWay}"/>
            <Button x:Name="Button" Content="Click Me" Command="{x:Bind AddItem}">
            </Button>
</StackPanel>

This is UserControl code behind code :

 public sealed partial class MyUserControl1 : UserControl
    {
        public MyUserControl1()
        {
            this.InitializeComponent();
            //   mygrid.DataContext = this;
            (this.Content as FrameworkElement).DataContext = this;
        }

        public static readonly DependencyProperty AddItemProperty =
          DependencyProperty.Register(
              "AddItem",
              typeof(ICommand),
              typeof(MyUserControl1), new PropertyMetadata(null));

        public ICommand AddItem
        {
            get { return (ICommand)GetValue(AddItemProperty); }
            set { SetValue(AddItemProperty, value); }
        }

        public static readonly DependencyProperty ComponentProperty = DependencyProperty.Register("Component",typeof(MyViewModel),typeof(MyUserControl1),new PropertyMetadata(null));

        public MyViewModel Component
        {
            get { return (MyViewModel)GetValue(ComponentProperty); }
            set { SetValue(ComponentProperty, value); }
        }

    }

UserControl View Model:

public class MyViewModel:ViewModelBase
    {
        public MyViewModel()
        {

        }
        public string Text => "ABC";
    }

Parent View Model:

  public class SettingsPartViewModel : ViewModelBase
  {
        DelegateCommand _MyCommand;

        public DelegateCommand MyCommand
            => _MyCommand ?? (_MyCommand = new DelegateCommand(async () =>
            {
                await Task.Run(() => {
                  ///Some Code  
                });
            }));
     }

Whenever I run code I get following Error:

 Unable to cast object of type 'WindowsApp2.ViewModels.SettingsPartViewModel' to type 'WindowsApp2.ViewModels.MyViewModel'. 

Whats going wrong here?


Solution

  • I think you're going wrong here Component="{Binding}". You're directly setting component to the parent view's DataContext i.e WindowsApp2.ViewModels.SettingsPartViewModel instead of WindowsApp2.ViewModels.MyViewModel.

    For it to work properly, you need to create an instance of MyViewModel in your SettingsPartViewModel and bind it to the Component.

    Try below sample :

    In SettingsPartViewModel :

    private MyViewModel myViewModelInstance = new MyViewModel();
    
    public MyViewModel MyViewModelInstance
    {
        get { return myViewModelInstance; }
        set { myViewModelInstance = value; //Raise NotifyPropertyChanged }
    }
    

    In SettingsPart.xaml :

    <vm:MyUserControl1  AddItem="{Binding MyCommand}"   Component="{Binding MyViewModelInstance}"  RelativePanel.Below="abc" />