使用 XAML 为多个控件设置数据上下文



我有绑定到不同类别的 ViewModel 类的不同控件组。

视图模型是

  • MainViewModel
  • VideoViewModel
  • AudioViewModel

问题

如何使用 XAML 而不是 C# 设置DataContext

1.我尝试将DataContext="{Binding VideoViewModel}"添加到ComboBox XAML,但它不起作用,并且项目为空。

2.我还尝试将UserControl内某个类别的所有ComboBoxesDataContext分组:

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

3.还尝试将<Window> DataContext设置为自身DataContext="{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 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"/>

视频视图模型类

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");
        }
    }
}

您可以在 xaml 中实例化对象:

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

您也可以为用户控件视图模型执行此操作。

更常见的情况是,任何子视图模型都在窗口视图模型中实例化。公开为公共属性和子视图模型的数据上下文,然后绑定到该属性。

我建议你先谷歌视图模型,看看一些样本。

我不确定这是否是正确的方法,但我能够将ComboBoxes组绑定到不同的 ViewModels。


我创建了一个视图模型来引用它们。

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 ();
}

我在MainWindow.xaml中使用了安迪的建议<local:VM>

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

并用了DataContext设置为VideoViewUserControl,里面有ComboBoxes

代替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";

其他人显然提供了很好的答案,但是,绑定的潜在缺失是主视图模型的第一组 DataContext = = = = = 。

一旦将主窗体的数据上下文连接到主视图模型,其下的每个控件都期望 ITS START 点作为主视图模型。 由于主视图模型在视频和音频视图模型的 IT 下没有公共属性,因此找不到要绑定的它们。

如果删除"这个。DataContext =",则没有默认的数据上下文,每个控件都应该能够按照您的预期进行绑定。

所以改变

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

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

相关内容

  • 没有找到相关文章