简体   繁体   中英

How to Create Custom UserControl with MVVM WPF architecture

Is it possible to create a custom control with dependencies properties respecting the MVVM WPF pattern?

If yes, how do you use the CustomControl in another MVVM application and expose the dependencies properties ?

EDIT:

Below a simple example that allows me to create a customControl then I use it in an another WPF App named "TestCustomControl". But, the dependency Property doesn't work at all for me.

在此输入图像描述

CustomControlView.xaml

<UserControl xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"  xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"  x:Class="MyCustomControl.MyCustomUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
         xmlns:myCustomControl="clr-namespace:MyCustomControl"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">

<dxmvvm:Interaction.Triggers>
    <dxmvvm:EventToCommand Command="{Binding LoadCommand}" EventName="Loaded" />
</dxmvvm:Interaction.Triggers>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <dxe:ButtonEdit Height="40" Grid.Row="0"/>
    <dxg:GridControl Grid.Row="1" ItemsSource="{Binding MyItems}" AutoGenerateColumns="AddNew"/>
</Grid>

CustomControlView.xaml.cs

using System.Windows;
using System.Windows.Controls;
namespace MyCustomControl
{
    /// <summary>
    /// Interaction logic for MyCustomUserControl.xaml
    /// </summary>
    public partial class MyCustomUserControl : UserControl
    {
        public MyCustomUserControl()
        {
            InitializeComponent();
            this.DataContext = new CustomControlViewModel(FilePath);
        }
        /// <summary>
        /// File Path 
        /// </summary>
        public static readonly DependencyProperty FilePathProperty = DependencyProperty.Register(
            "FilePath", typeof(string), typeof(MyCustomUserControl), new PropertyMetadata(string.Empty));
        public string FilePath
        {
            get { return (string)GetValue(FilePathProperty); }
            set
            {
                SetValue(FilePathProperty, value);
            }
        }
    }
}

CustomControlViewModel.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using DevExpress.Mvvm;
using DevExpress.Mvvm.DataAnnotations;
namespace MyCustomControl
{
    public class CustomControlViewModel:ViewModelBase
    {
        #region Fields
        private ObservableCollection<string> _myItems;
        private string _path;
        #endregion

        #region Constructors
        public CustomControlViewModel(string path)
        {
            _path = path;
        }
        #endregion

        #region Commands

        [Command]
        public void Load()
        {
            IEnumerable<string> allLinesText = new List<string>();
            try
            {
                allLinesText = File.ReadAllLines(_path).ToList();
            }
            catch (Exception e)
            {

                Console.WriteLine(e.ToString());
            }

            MyItems = new ObservableCollection<string>(allLinesText);
        }
        #endregion

        #region Properties
        public ObservableCollection<string> MyItems
        {
            get { return _myItems; }
            set { SetProperty(ref _myItems, value, () => MyItems); }
        }
        #endregion
    }
}

MainWindow.xaml

<Window xmlns:MyCustomControl="clr-namespace:MyCustomControl;assembly=MyCustomControl"  
    x:Class="TestCustomControl.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:testCustomControl="clr-namespace:TestCustomControl"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <testCustomControl:MainViewModel/>
</Window.DataContext>
<Grid>
    <MyCustomControl:MyCustomUserControl FilePath="{Binding MyFile}"/>
</Grid>

MainViewModel.cs

using DevExpress.Mvvm;
namespace TestCustomControl
{
    public class MainViewModel: ViewModelBase
    {
        #region Fields
        private string _myFile;        
        #endregion

        #region Constructors
        public MainViewModel()
        {
            MyFile = "List.txt";
        }
        #endregion

        #region Properties
        public string MyFile
        {
            get { return _myFile; }
            set { SetProperty(ref _myFile, value, () => MyFile); }
        }
        #endregion
    }
}

NB: "List.txt" is a file placed into "..\\TestCustomControl\\bin\\Debug"

Can Someone help me to find why my dependency property doesn't work ?

It's obviously possible and it's the best way to create a custom control. Because without dependency properties we can't easily reuse a custom control. Re-usability becomes very much easier with dependency properties. You could event use ICommand as Dependency properties thereby following MVVM pattern and having a much cleaner code behind.

If I elaborate on how to reuse a CustomControl in another MVVM application it would be too broad to be answered here. YOu could just go to Visual studio and create a custom control. In the code behind define a few dependency properties which are bound to properties which you think are dynamic, in the view. Reuse this very customcontrol in another application and set these properties while reusing it.

You could also try out with an ICommand for routing some event to the view model. ie the Dependency Property for an List item selection changed event could route a command to the corresponding view model.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM