Установите DataContext для нескольких элементов управления с XAML - PullRequest
0 голосов
/ 05 апреля 2019

У меня есть разные группы элементов управления, привязанные к разным категориям классов ViewModel.

Модели ViewModel

  • MainViewModel
  • VideoViewModel
  • AudioViewModel

Вопрос

Как установить DataContext с XAML вместо C #?

1. Я попытался добавить DataContext="{Binding VideoViewModel}" к ComboBox XAML, но это не сработало, и элементы оказались пустыми.

2. Iтакже попытался сгруппировать все ComboBoxes определенной категории в UserControl с DataContext:

<UserControl DataContext="{Binding VideoViewModel}">
    <!-- ComboBoxes in here -->
</UserControl>

3. Также попытался установить <Window> DataContextDataContext="{Binding RelativeSource={RelativeSource Self}}"


Контекст данных

В настоящее время я устанавливаю DataContext таким образом для различных категорий элементов управления:

public MainWindow()
{
    InitializeComponent();

    // Main
    this.DataContext =
    tbxInput.DataContext =
    tbxOutput.DataContext =
    cboPreset.DataContext =
    MainViewModel.vm;

    // Video
    cboVideo_Codec.DataContext =
    cboVideo_Quality.DataContext =
    tbxVideo_BitRate.DataContext =
    cboVideo_Scale.DataContext =
    VideoViewModel.vm;

    // Audio
    cboAudio_Codec.DataContext =
    cboAudio_Quality.DataContext =
    tbxAudio_BitRate.DataContext =
    tbxAudio_Volume.DataContext =
    AudioViewModel.vm;
}

XAML ComboBox

<ComboBox x:Name="cboVideo_Quality" 
          DataContext="{Binding VideoViewModel}"
          ItemsSource="{Binding Video_Quality_Items}"
          SelectedItem="{Binding Video_Quality_SelectedItem}"
          IsEnabled="{Binding Video_Quality_IsEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
          HorizontalAlignment="Left" 
          VerticalAlignment="Top" 
          Width="105" 
          Height="22"
          Margin="0,0,0,0"/>

Видео ViewModel Class

public class VideoViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    private void OnPropertyChanged(string prop)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(prop));
        }
    }


    public VideoViewModel() { }


    public static VideoViewModel _vm = new VideoViewModel();
    public static VideoViewModel vm
    {
        get { return _vm; }
        set
        {
            _vm = value;
        }
    }

    // Items Source
    private List<string> _Video_Quality_Items = new List<string>()
    {
        "High",
        "Medium",
        "Low",
    };
    public List<string> Video_Quality_Items
    {
        get { return _Video_Quality_Items; }
        set
        {
            _Video_Quality_Items = value;
            OnPropertyChanged("Video_Quality_Items");
        }
    }

    // Selected Item
    private string _Video_Quality_SelectedItem { get; set; }
    public string Video_Quality_SelectedItem
    {
        get { return _Video_Quality_SelectedItem; }
        set
        {
            if (_Video_Quality_SelectedItem == value)
            {
                return;
            }

            _Video_Quality_SelectedItem = value;
            OnPropertyChanged("Video_Quality_SelectedItem");
        }
    }

    // Enabled
    private bool _Video_Quality_IsEnabled;
    public bool Video_Quality_IsEnabled
    {
        get { return _Video_Quality_IsEnabled; }
        set
        {
            if (_Video_Quality_IsEnabled == value)
            {
                return;
            }

            _Video_Quality_IsEnabled = value;
            OnPropertyChanged("Video_Quality_IsEnabled");
        }
    }
}

Ответы [ 3 ]

0 голосов
/ 09 апреля 2019

Я не уверен, что это правильный путь, но мне удалось связать группы ComboBoxes с различными моделями представления.


Я создал одну модель представления для ссылки на них всех.

public class VM: INotifyPropertyChanged
{
    ...

    public static MainViewModel MainView { get; set; } = new MainViewModel ();
    public static VideoViewModel VideoView { get; set; } = new VideoViewModel ();
    public static AudioViewModel AudioView { get; set; } = new AudioViewModel ();
}

Я использовал предложение Энди <local:VM> в MainWindow.xaml.

<Window x:Class="MyProgram.MainWindow"
        ...
        xmlns:local="clr-namespace:MyProgram"
        >
    <Window.DataContext>
        <local:VM/>
    </Window.DataContext>

И использовал UserControl с DataContext, установленным на VideoViewComboBoxes внутри.

Вместо UserControl можно также просто использовать VideoView.Your_Property_Name для каждой привязки.

<UserControl DataContext="{Binding VideoView}">
    <StackPanel>
        <ComboBox x:Name="cboVideo_Quality" 
                  ItemsSource="{Binding Video_Quality_Items}"
                  SelectedItem="{Binding Video_Quality_SelectedItem}"
                  IsEnabled="{Binding Video_Quality_IsEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                  HorizontalAlignment="Left" 
                  VerticalAlignment="Top" 
                  Width="105" 
                  Height="22"
                  Margin="0,0,0,0"/>

        <!-- Other ComboBoxes with DataContext VideoView in here -->

    </StackPanel>
</UserControl>

Затем для доступа к одному из свойств:

VM.VideoView.Video_Codec_SelectedItem = "x264";
VM.VideoView.Video_Quality_SelectedItem = "High";

VM.AudioView.Audio_Codec_SelectedItem = "AAC";
VM.AudioView.Audio_Quality_SelectedItem = "320k";
0 голосов
/ 09 апреля 2019

Другие, очевидно, предоставили хорошие ответы, однако основной промах вашей привязки - это ваш первый набор DataContext = = = = = для модели основного представления.Модель ОСНОВНОГО вида, каждый элемент управления ожидает, что ЕГО НАЧИНАЕТСЯ как модель ОСНОВНОГО представления.Поскольку модель MAIN view не имеет открытого свойства ПОД моделями видео и аудио, она не может найти их для привязки do.

Если вы удалите «this.DataContext =», то будетнет контекста данных по умолчанию, и каждый элемент управления ДОЛЖЕН быть в состоянии связать их так, как вы предполагали.

Так что измените

this.DataContext =
tbxInput.DataContext =
tbxOutput.DataContext =
cboPreset.DataContext =
MainViewModel.vm;

на

tbxInput.DataContext =
tbxOutput.DataContext =
cboPreset.DataContext =
MainViewModel.vm;
0 голосов
/ 05 апреля 2019

Вы можете создать экземпляр объекта в xaml:

  <Window.DataContext>
      <local:MainWindowViewmodel/>
  </Window.DataContext>

И вы можете сделать это и для своих моделей представления usercontrol.

Обычно для любых дочерних моделей представления в экземпляре более обычноокно просмотра модели.Предоставляется в качестве общедоступных свойств и текстового контекста дочерней модели представления, а затем привязывается к этому свойству.

Я предлагаю вам сначала посмотреть Google ViewModel и взглянуть на некоторые примеры.

...