2014-08-27 47 views
3

我是WPF的新手,並將從VC++ 6.0/MFC應用程序移植到c#/ WPF(VS2013)。我的Windows開發大部分都在VC++/MFC中。我試圖堅持使用MVVM模式,並且正在撰寫一些概念應用程序的證明,以便讓我的腳溼潤。到目前爲止,我有一個棘手的問題。WPF在同一個窗口中更改Datacontexts和視圖

當我的應用程序啓動時,它將呈現客戶和賬單的樹視圖。我已經使用一個簡單的分層數據模板,並且每個級別綁定到我的本地數據類型(視圖模型),可以很好地工作。我想要發生的是當一個賬單被選中(現在我有一個按鈕在賬單模板上)我希望樹狀圖被替換爲賬單的詳細視圖(我不想讓對話框彈出向上)。 Startup Screen

XAML中的是這樣的:

<DockPanel> 
    <TreeView x:Name="trvGroups" ItemsSource="{Binding LBGroups}" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling"> 
    <TreeView.ItemContainerStyle> 
     <!-- 
      This Style binds a TreeViewItem to a LBtreeViewItemViewModel 
     --> 
     <Style TargetType="{x:Type TreeViewItem}"> 
      <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" /> 
      <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> 
      <Setter Property="FontWeight" Value="Normal" /> 
     </Style> 
    </TreeView.ItemContainerStyle> 

    <TreeView.Resources> 
     <HierarchicalDataTemplate 
      DataType="{x:Type local:GroupViewModel}" 
      ItemsSource="{Binding Children}" 
      > 
      <StackPanel Orientation="Horizontal"> 
       <TextBlock Text="{Binding GroupName}" /> 
      </StackPanel> 
     </HierarchicalDataTemplate> 

     <HierarchicalDataTemplate 
      DataType="{x:Type local:BillViewModel}" 
      ItemsSource="{Binding Children}"> 
      <StackPanel Orientation="Horizontal"> 
       <TextBlock Text="{Binding BillName}" /> 
       <Button Command="{Binding Path=BillEditCommand}">Edit</Button> 
      </StackPanel> 
     </HierarchicalDataTemplate> 
    </TreeView.Resources> 
    </TreeView> 
</DockPanel> 

現在我有比什麼都重要的問題。我應該將每個視圖定義爲用戶控件並將其放入window.resources中嗎?我是否使用數據模板?我假設我會更改數據上下文以指向明細帳單視圖模型。做這個的最好方式是什麼?我堅持使用MVVM的理解是,我的目標是在代碼背後沒有任何東西(或儘可能少)。

我在尋找更多的指針,讓我沿着正確的道路開始研究。我現在有點困惑。

在此先感謝。

+2

每個視圖應該是一個'UserControl'(或'Window'),並有自己的XAML文件和相應的(大部分是空的)後面的代碼文件。您不在'Windows.Resources'中定義視圖。但是,您可以在任何可插入標準控件的位置插入「UserControl」,並可顯示「窗口」。 – 2014-08-27 20:22:17

+1

業務邏輯進入視圖模型。用戶界面關注點在代碼隱藏中。 MVVM!=沒有隱藏代碼。 – Will 2014-08-27 20:30:29

+0

閱讀關於MVVM中的Master/Details場景 – 2014-08-27 20:30:49

回答

1

我會告訴你一個普通的主控細節場景,你可以在你的TreeView中選擇模型並編輯他們。

CS:

 public partial class MainWindow : Window , INotifyPropertyChanged 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     this.DataContext = this; 
    } 

    private ICommand onEditBillCommand; 
    public ICommand OnEditBillCommand 
    { 
     get 
     { 
      if (onEditBillCommand == null) 
       onEditBillCommand = new RelayCommand<Bill> 
        (
         bill => { CurrentBill = bill; } 
        ); 
      return onEditBillCommand; 
     } 
    } 

    private Bill currectBill; 
    public Bill CurrentBill 
    { 
     get { return currectBill; } 
     set 
     { 
      currectBill = value; 
      PropertyChanged(this, new PropertyChangedEventArgs("CurrentBill")); 
     } 
    } 

    public List<Customer> Customers 
    { 
     get 
     { 
      List<Customer> customers = new List<Customer>(); 
      for (int i = 0; i < 5; i++) 
      { 
       customers.Add(CreateMockCustomer(i)); 
      } 
      return customers; 
     } 
    } 

    private Customer CreateMockCustomer(int g) 
    { 
     Customer c = new Customer(); 

     c.Name = "John (" + g + ")" ; 

     for (int i = 0; i < 3; i++) 
     { 
      c.Bills.Add(CreateMockBill()); 
     } 

     return c; 
    } 

    private Bill CreateMockBill() 
    { 
     Bill b = new Bill(); 

     b.Price = 55.5; 
     b.BoughtOnDate = DateTime.Now.Date; 

     return b; 
    } 

    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
} 


public class Customer : INotifyPropertyChanged 
{ 
    private string name; 
    public string Name 
    { 
     get { return name; } 
     set { name = value; } 
    } 

    private ObservableCollection<Bill> bills; 
    public ObservableCollection<Bill> Bills 
    { 
     get 
     { 
      if (bills == null) 
      { 
       bills = new ObservableCollection<Bill>(); 
      } 
      return bills; 
     } 
    } 


    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
} 

public class Bill : INotifyPropertyChanged 
{ 
    private double price; 
    public double Price 
    { 
     get { return price; } 
     set 
     { 
      price = value; 
      PropertyChanged(this, new PropertyChangedEventArgs("Price")); 
     } 
    } 

    private DateTime boughtOnDate; 
    public DateTime BoughtOnDate 
    { 
     get { return boughtOnDate; } 
     set 
     { 
      boughtOnDate = value; 
      PropertyChanged(this, new PropertyChangedEventArgs("BoughtOnDate")); 
     } 
    } 


    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
} 

public interface IRelayCommand : ICommand 
{ 
    void RaiseCanExecuteChanged(); 
} 
public class RelayCommand<T> : IRelayCommand 
{ 
    private Predicate<T> _canExecute; 
    private Action<T> _execute; 

    public RelayCommand(Action<T> execute, Predicate<T> canExecute = null) 
    { 
     _execute = execute; 
     _canExecute = canExecute; 
    } 

    private void Execute(T parameter) 
    { 
     _execute(parameter); 
    } 

    private bool CanExecute(T parameter) 
    { 
     return _canExecute == null ? true : _canExecute(parameter); 
    } 

    public bool CanExecute(object parameter) 
    { 
     return parameter == null ? false : CanExecute((T)parameter); 
    } 

    public void Execute(object parameter) 
    { 
     _execute((T)parameter); 
    } 

    public event EventHandler CanExecuteChanged; 

    public void RaiseCanExecuteChanged() 
    { 
     var temp = Volatile.Read(ref CanExecuteChanged); 

     if (temp != null) 
      temp(this, new EventArgs()); 
    } 
} 

XAML:

 <Window> 
     <Window.Resources> 
      <HierarchicalDataTemplate x:Key="customerTemplate" DataType="{x:Type local:Customer}" ItemsSource="{Binding Bills}"> 
       <HierarchicalDataTemplate.ItemTemplate> 
        <DataTemplate> 
        <Grid> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition/> 
          <ColumnDefinition/> 
          <ColumnDefinition/> 
         </Grid.ColumnDefinitions> 

         <TextBlock Text="{Binding Price}" /> 
         <TextBlock Text="{Binding BoughtOnDate}" Grid.Column="1" /> 
         <Button Content="Edit" Grid.Column="2" 
          Command="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=DataContext.OnEditBillCommand}" 
          CommandParameter="{Binding}"/> 

        </Grid> 
       </DataTemplate> 
      </HierarchicalDataTemplate.ItemTemplate> 

      <TextBlock Text="{Binding Name}" FontFamily="Arial" FontSize="16" FontWeight="Bold" /> 

     </HierarchicalDataTemplate> 

    </Window.Resources> 

    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition /> 
      <ColumnDefinition Width="0.05*"/> 
      <ColumnDefinition /> 
     </Grid.ColumnDefinitions> 


     <TreeView ItemsSource="{Binding Customers}" ItemTemplate="{StaticResource customerTemplate}"> 

     </TreeView> 


     <Grid Grid.Column="2" DataContext="{Binding CurrentBill, Mode=OneWay}" Background="AliceBlue"> 
      <Grid.RowDefinitions> 
       <RowDefinition /> 
       <RowDefinition /> 
      </Grid.RowDefinitions> 

      <TextBox Text="{Binding Price, Mode=TwoWay}" Margin="50"/> 
      <TextBox Text="{Binding BoughtOnDate, Mode=TwoWay}" Grid.Row="1" Margin="50"/> 


     </Grid> 

    </Grid>  
+0

這與我想要的很接近,除非我希望樹形視圖在顯示細節時「消失」(然後在細節關閉時重新出現)。讓我玩這個和上面的其他想法。 – 2014-08-28 14:43:27

+0

是的,我知道,我認爲你可以從這裏提取。 沒問題,我不能編輯這個來做到這一點。 – 2014-08-28 14:52:37