使用XAML为多个控件设置DataContext

问题描述 投票:-1回答:3

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

ViewModels是

  • MainViewModel
  • VideoViewModel
  • AudioViewModel

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

1.我尝试将DataContext="{Binding VideoViewModel}"添加到ComboBox XAML中,但它没有用,而且这些项目都是空的。

2.我还尝试将ComboBoxes中某个类别的所有UserControlDataContext分组:

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

3.还尝试将<Window> DataContext设置为自己DataContext="{Binding RelativeSource={RelativeSource Self}}"


Data Context

我正在以这种方式为不同类别的控件设置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"/>

Video 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");
        }
    }
}
c# wpf mvvm data-binding viewmodel
3个回答
0
投票

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

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

您也可以为usercontrol视图模型执行此操作。

在窗口视图模型中实例化任何子视图模型更常见。作为公共属性公开,子视图模型的datacontext然后绑定到该属性。

我建议你先google viewmodel然后看看一些样本。


0
投票

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


我创建了一个ViewModel来引用它们。

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>使用了Andy的建议MainWindow.xaml

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

并使用UserControlDataContext设置为VideoView,内部有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";

0
投票

其他人显然提供了很好的答案,但是,绑定的基础错误是您对主视图模型的第一组DataContext = = = = =。

一旦您将主窗体的数据上下文连接到MAIN视图模型,其下的每个控件都希望ITS STARTING点作为MAIN视图模型。由于MAIN视图模型没有视频和音频视图模型的公共属性,因此无法找到它们绑定do。

如果你删除“this.DataContext =”,那么就没有默认的数据上下文,每个控件都应该按照你的意图绑定。

所以改变

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

tbxInput.DataContext =
tbxOutput.DataContext =
cboPreset.DataContext =
MainViewModel.vm;
© www.soinside.com 2019 - 2024. All rights reserved.