Как установить DataBinding для UserControl с ViewModel - PullRequest
0 голосов
/ 25 марта 2019

У меня есть пользовательский контроль с парой элементов управления внутри. Поэтому я решил использовать ViewModel для управления всеми этими привязываемыми значениями. Но я считаю, что моя привязка всегда нулевая. Итак, как настроить привязку для ViewModel в usercontrol

MainWindows.xaml

<Window x:Class="Test.MainWindow"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel>
        <cus:Wizard WizardModel="{Binding MyModel}"/>
    </StackPanel>
</Window>

MainWindows.xaml.cs

public partial class MainWindow : Window
{
   private ViewModel vm = new ViewModel();
   public MainWindow()
   {
        InitializeComponent();
        DataContext = vm;
   }
}

ViewModel.cs (модель представления главного окна)

    public class ViewModel : INotifyPropertyChanged
    {
        private Model _MyModel;
        public Model MyModel
        {
            get
            {
                return _MyModel;
            }
            set
            {
                _MyModel = value;
                NotifyPropertyChanged("MyModel");
            }
        }
    }

Wizard.xaml (мой UserControl)

<UserControl mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Something}" />
    </Grid>
</UserControl>

Wizard.xaml.cs

public partial class Wizard : UserControl
{
    private readonly object modelLock = new object();
    private Model CurrentModel = new Model();
    public Wizard()
    {
        InitializeComponent();
        DataContext = CurrentModel;
    }     
    public Model WizardModel
    {
        get { return (Model)this.GetValue(WizardModelProperty); }
        set { this.SetValue(WizardModelProperty, value); }
    }
    public static readonly DependencyProperty WizardModelProperty = DependencyProperty.Register("WizardModel", typeof(Model), typeof(Wizard), new PropertyMetadata(null, new PropertyChangedCallback(ModelChanged)));
    private static void ModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((Wizard)d).OnModelChanged();
    }
    private void OnModelChanged()
    {
        lock (this.modelLock)
        {
            if(CurrentModel != null)
            {
                CurrentModel = null;
            }
            if (WizardModel != null)
            {
                CurrentModel = WizardModel;                    
            }
        }
    }
}

WizardModel в UserControl всегда равен нулю. Итак, как настроить эту ViewModel в UserControl

1 Ответ

0 голосов
/ 25 марта 2019

UserControl, который должен работать с конкретным классом модели представления - или, точнее, с классом с определенным набором открытых свойств - может напрямую связываться со свойствами модели представления в своем XAML.

Учитываямодель представления, такую ​​как

public class Model
{
    public string Something { get; set; }
}

, вы можете написать UserControl, содержащий не более чем этот XAML

<UserControl ...>
    ...
    <TextBox Text="{Binding Something}" />
    ...
</UserControl>

и этот код

public partial class Wizard : UserControl
{
    public Wizard()
    {
        InitializeComponent();
    }  
}

Если вы сейчас установитеего DataContext для экземпляра Model (или любого другого класса со свойством Something), он будет просто работать:

<local:Wizard DataContext="{Binding MyModel}"/>

, так как значение свойства DataContext наследуется от родительских к дочерним элементамэто также будет работать:

<StackPanel DataContext="{Binding MyModel}">
    <local:Wizard/>
</StackPanel>

Однако UserControl все еще зависит от существования свойства Something в его DataContext.Чтобы избавиться от этой зависимости, ваш элемент управления может предоставить свойство зависимости

public static readonly DependencyProperty MyTextProperty =
    DependencyProperty.Register(nameof(MyText), typeof(string), typeof(Wizard));

public string MyText
{
    get { return (string)GetValue(MyTextProperty); }
    set { SetValue(MyTextProperty, value); }
}

и связать элемент в его XAML с его собственным свойством

<UserControl ...>
    ...
    <TextBox Text="{Binding MyText,
        RelativeSource={RelativeSource AncestorType=UserControl}}"/>
    ...
</UserControl>

Теперь вы должны связатьсвойство элемента управления вместо установки его DataContext:

<local:Wizard MyText="{Binding MyModel.Something, Mode=TwoWay}"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...