【问题标题】:Binding to Child Class of DataContext绑定到 DataContext 的子类
【发布时间】:2011-09-02 22:11:11
【问题描述】:

我有一个 WPF 窗口,左侧有一个任务列表,右侧有所选任务的详细信息。 tasks只是task的集合,可以考虑POCO。

具有任务和选定任务的单个 ViewModel

public class TaskViewModel
{
    public TaskViewModel()
    {
        Tasks = new Task().GetTasks();
    }


    // A LIST OF MANY TASKS
    private Tasks _tasksViewModel;
    public Tasks Tasks
    {
        get { return _tasksViewModel; }
        private set
        {
            _tasksViewModel= value;
        }
    }


    // A SINGLE SELECTED TASK
    private static readonly DependencyProperty CurrentTaskProperty = DependencyProperty.Register(
        "CurrentTask", typeof(Task), typeof(TaskViewModel), new PropertyMetadata(null));
    public Task CurrentTask
    {
        get { return (Task) GetValue(CurrentTaskProperty); }
        set { SetValue(CurrentTaskProperty, value); }
    }
}

XAML 中的窗口:

<Window>
    <!-- A List with multiple tasks. -->
    <ListBox x:Name="listBoxTasks" ItemsSource="{Binding Path=Task, Mode=TwoWay} />

    <!-- The List's selected task's "Task Name" property. -->
    <TextBox x:Name="textBoxTaskName" Text="{Binding Path=CurrentTask, Mode=TwoWay}" />    

    <!-- The List's selected tasks' "Task Items" child objects. -->
    <ListBox x:Name="listBoxTaskItems" ItemsSource="{Binding Path=EditableValue, Mode=TwoWay}" />
</Window>

还有我的 MainWindow xaml 代码隐藏:

public partial class MainWindow : Window
{
    private MainWindow()
    {
        DataContext = _tasksViewModel;
    }

    private void OnListBoxTasksSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        _tasksViewModel.CurrentTask = task;
        DataContext = _tasksViewModel;
    }
}

现在是问题:

我应该有多少个视图模型?

  • 我应该添加第二个 ViewModel 吗?我应该有一个 ViewModel 用于 Tasks,一个 ViewModel 用于选定的 Task,还是应该只有一个 ViewModel 用于整个窗口?

在 XAML 中绑定以及在 C# 中设置数据上下文的最佳方式是什么?

  • 我怎样才能让整个窗口只有一个 DataContext?如果 Window 的 DataContext 是 TasksViewModel,如何将某些东西绑定到 TasksViewModel.CurrentTask?有没有办法绑定到 Window.DataContext 的子项的属性,还是我需要为使用 CurrentTask 的任何控件手动指定单独的 DataContext?

    • 有没有这样的方法:

在 C# 中:

DataContext = _tasksViewModel.Tasks

在 XAML 中:

<!-- Can I do something similar to DataContext.CurrentTask.TaskName ??? -->
<TextBox x:Name="textBoxTaskName" MinWidth="100" Text="{Binding Path=DataContext.CurrentTask.TaskName, Mode=TwoWay}" />

<!-- What about DataContext.CurrentTask.TaskItems??? -->
<ListBox x:Name="listBoxTaskItems" ItemsSource="{Binding Path=**DataContext.CurrentTask.TaskItems**, DisplayMember="TaskItemName}" />

或者换句话说,有没有比这样做更好的解决方案:

 // When a Task in Tasks is selected...
OnListBoxTasksSelectionChanged()
{
    [...]

    // Set that Task as the DataContext for other controls
    textBoxTaskName.DataContext = Task;

    listBoxTaskItems.DataContext = Task.TaskItems;
 }

【问题讨论】:

    标签: c# wpf xaml data-binding binding


    【解决方案1】:

    Binding 中的路径可以深入绑定到 DataContext 的属性中。级别由一个点分隔。您还可以从绑定中访问索引器。

    如果您的 DataContext 是例如通过说{Binding CurrentTask} 绑定到 CurrentTask 的 TasksViewModel。此外,您通常会将 ListBoxSelectedItem 绑定到 CurrentTask

    明显的错误是试图从 DependencyObject 继承为 ViewModel 并指定依赖属性。在要指定绑定的地方需要依赖属性。 ViewModel 只是数据源。

    因此,正确的方法是实现 INotifyPropertyChanged 并通过引发您的哪些属性更改的事件来通知 WPF

    【讨论】:

    • 这是绑定文本框的正确语法吗?当我的 SelectedTask 更改时,我仍然无法显示它。 &lt;TextBox x:Name="textBoxTaskName" Text="{Binding CurrentTask, Path=Key, Mode=TwoWay}" /&gt; private Task _currentTask; public Task CurrentTask { get { return _currentTask; } set { _currentTask = value; OnPropertyChanged("CurrentTask"); OnPropertyChanged("CurrentTask.TaskName"); OnPropertyChanged("TaskName"); ..
    • 绑定的默认参数是“Path”,所以您基本上是在声明 Path 两次(CurrentTask, Key) - 尝试将它们组合起来:Path=CurrentTask.Key
    猜你喜欢
    • 2016-07-11
    • 1970-01-01
    • 2013-02-02
    • 2011-10-13
    • 1970-01-01
    • 2015-01-21
    • 2011-05-19
    • 2011-10-17
    • 2016-09-06
    相关资源
    最近更新 更多