2011-09-02 104 views
0

我有一個WPF窗口,其任務列表在左側,有關右側選定任務的詳細信息。任務只是一個任務的集合,你可以考慮它的POCO。綁定到DataContext的子類

單視圖模型兼具任務和所選擇的任務

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> 

而我的主窗口的XAML代碼隱藏:

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

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

而現在的問題:

我應該有多少個視圖模型有哪些?

  • 我應該添加第二個ViewModel嗎?我是否應該有一個用於任務的ViewModel,另一個用於所選的任務,或者我應該只有一個ViewModel用於整個窗口?

什麼是最好的方式來綁定在XAML,並在C#中設置數據上下文(S)?

  • 如何爲整個窗口只有一個DataContext?如果窗口的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; 
} 

回答

2

在你的綁定可以深深綁定到DataContext的性能的路徑。級別由點分隔。您還可以從綁定中訪問索引器。

如果你的DataContext是例如TasksViewModel通過說{Binding CurrentTask}綁定到CurrentTask。此外,您通常會將您的列表框選定的項目複製到CurrentTask

試圖從DependencyObject作爲ViewModel繼承並指定依賴項屬性是明顯錯誤的。需要指定綁定的依賴項屬性。 ViewModels只是數據源。

因此,正確的做法是實施INotifyPropertyChanged的和notity通過提高其你的屬性而改變

+0

這是綁定文本框中正確的語法事件WPF?當我的SelectedTask改變時,仍然無法顯示它。 ' private Task _currentTask; public Task CurrentTask { get {return _currentTask; } set { _currentTask = value; OnPropertyChanged(「CurrentTask」); OnPropertyChanged(「CurrentTask.TaskName」); OnPropertyChanged(「TaskName」); ..' – Shawn

+0

綁定的默認參數是「路徑」,所以基本上聲明路徑兩次(CurrentTask,Key) - 嘗試組合它們:Path = CurrentTask.Key – flq