Настройка свойства ViewModel из XAML

#c# #wpf #xaml

#c# #wpf #xaml

Вопрос:

У меня есть некоторые, UserControl они DataContext привязаны к ViewModel, Как установить свойство ViewModel из XAML ? Возможно ли это?

UPD : Извините за то, что не очень понятно, я пытаюсь получить что-то вроде этого: DataContext UserControl привязан к ViewModel, мне нужно присвоить свойству ViewModel какое-то значение (скажем, свойству Width UserControl). Возможно ли это?

UPD2: Кажется, это невозможно.Я знаю о режиме привязки TwoWay и т.д., Что я хотел сделать — установить свойство ViewModel равным свойству UserControl

Этот пример должен быть очень понятным

 <Set Property={Binding SomePropertyOnViewModel} 
     Value={Binding RelativeSource={RelativeSource Self}, 
                    Path=SomePropertyOnUserControl}>
  

Комментарии:

1. Учитывая опубликованный вами псевдо-XAML, почему <UserControl SomePropertyOnUserControl=»{Привязка SomePropertyOnViewModel, Mode=OneWayToSource}» /> не работает для вас? Чего именно вы хотите достичь (в увеличенном виде)?

2. Я хотел бы использовать привязку при определении свойства в UserControl, как в псевдо-xaml

3. вы можете выполнить привязку ко всем нужным свойствам DependencyProperties. итак, если ваш UserControl имеет какие-либо свойства DependencyProperties, вы можете привязаться к нему.

4. требование (или, скорее, необходимость) все еще не ясна. Вы хотите установить значение SomePropertyOnViewModel для определенного события? Можете ли вы опубликовать больше кода о том, чего вы хотите достичь?

Ответ №1:

Я не уверен, точно ли я понимаю вопрос.

Но вот пример. Это приведет:

  • Создайте модель представления типа ExampleViewModel внутри пользовательского элемента управления, установив свойство user controls DataContext в xaml

  • Создайте текстовое поле в xaml и привяжите его к строковому свойству view models TextInViewModel .

  • Настройте обычный INotifyPropertyChanged интерфейс (он был извлечен из базового класса ViewModelBase )

Создайте модель представления в xaml и задайте для нее контекст данных пользовательских элементов управления:

 <UserControl x:Class="MyUserControl"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Test" 
            xmlns:viewModel="clr-namespace:ViewModels"> 
        <UserControl.DataContext>
            <viewModel:ExampleViewModel/>
        </UserControl.DataContext>

        <StackPanel Orientation="Horizontal" >
            <Label>Enter Text here: </Label>
            <TextBox Text="{Binding TextInViewModel}"></TextBox>
        </StackPanel>
</UserControl>
  

ViewModel:

 public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged(string prop)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }

}


public class ExampleViewModel : ViewModelBase 
{
    /// <summary>
    /// Property bound to textbox in xaml.
    /// </summary>
    public String TextInViewModel
    {
        get { return _textInViewModel; }
        set
        {
            _textInViewModel= value;
            RaisePropertyChanged("TextInViewModel");
        }
    }
    private string _textInViewModel;

    /// <summary>
    /// Constructor.
    /// </summary>
    public ExampleViewModel()
    {

    }
}
  

Ответ №2:

Привязка работает в обоих направлениях: т. е. от источника (например, viewmodel) к цели (например, usercontrol) и от цели обратно к источнику.
Вы указываете направление с помощью режима привязки.

Ниже приведены режимы привязки:

  • TwoWay
  • OneWay
  • Одноразовый
  • OneWayToSource

В вашем случае, если вы хотите привязать свойство width из usercontrol к свойству TheWidth ViewModel:

Случай A:

Хотите выполнить привязку в обоих направлениях, используйте Mode= TwoWay

 <UserControl Width="{Binding TheWidth, Mode=TwoWay}">
<!-- your rest of code -->
</UserControl>
  

Случай B:

Хотите привязать к viewmodel только usercontrol, используйте Mode=OneWayToSource

 <UserControl Width="{Binding TheWidth, Mode=OneWayToSource}">
<!-- your rest of code -->
</UserControl>
  

Комментарии:

1. да, я думал, это для silverlight, в wpf у вас есть onewaytosource, который является правильным ответом

Ответ №3:

XAML

    <UserControl.DataContext>
        <vm:ViewModel/>
    </UserControl.DataContext>
  

Комментарии:

1. Хорошо, это установит DataContext для UserControl в new ViewModel(), так что …?

Ответ №4:

Я предпочитаю подход с локатором ViewModel (это похоже на шаблон поиска служб для ViewModel). Потому что, как только ваша ViewModel имеет параметры конструктора, вы либо тесно связаны, либо не можете использовать описанный выше способ xaml….

Существует множество способов определения местоположения ViewModel. Один из них описан здесь с использованием MEF и silverlight. http://johnpapa.net/simple-viewmodel-locator-for-mvvm-the-patients-have-left-the-asylum

вот еще один:http://brendan.enrick.com/post/Wire-up-your-ViewModels-using-a-Service-Locator.aspx

Ответ №5:

Ну, вы привязываете к ним свои элементы пользовательского интерфейса:

 <UserControl Width="{Binding Path=DisplayWidth, Mode=OneWayToSource}">
    <Grid>
        <TextBox MinWidth=100 Text="{Binding MyProperty}"/>
    </Grid>
</UserControl>
  

предполагая, что модель представления выглядит следующим образом:

 class ViewModel
{
    public string MyProperty { get; set; }
    public int DisplayWidth { get; set; }
}
  

Комментарии:

1. Этот код привязывает что-то из UserControl к чему-то из ViewModel, проблема в том, что мне нужно, чтобы это было наоборот

2. Затем вы можете использовать Text=»{Привязка MyProperty, Mode=OneWayToSource}»

3. Нет, текст не является свойством ViewModel, смотрите мое описание в UPD

Ответ №6:

Через привязку, мой дорогой друг..

например: (предполагая в вашем контексте)

Если у вас есть класс «Person» и у вашего пользователя есть общедоступное свойство Name и FamIlyи вы хотите привязать его к текстовому полю. Вы делаете следующее:

 <TextBox Text="{Binding Path=Name}" />
  

Это работает только в том случае, если имя является вашим общедоступным свойством, лучше всего сделать ваш объект (в данном случае Person) общедоступным свойством и использовать параметр Path по-другому.

Пример:

 <TextBox Text="{Binding Path=Person.Name}" />
  

Это намного меньше загромождает ваш код, чем создание свойства в вашей viewmodel для каждого свойства любого объекта в вашей viewmodel.

Ответ №7:

«Как установить свойство ViewModel из XAML? Возможно ли это?»

Итак, это кажется невозможным, максимум, что вы можете выполнить — двусторонняя привязка, чего, к сожалению, я не хотел. В целом, это скорее плохой дизайн, чем проблема