WPF在同一窗口中更改Datacontexts和视图

时间:2014-08-27 20:14:26

标签: wpf mvvm

我是WPF am的新手,将VC ++ 6.0 / MFC中的应用程序移植到c#/ WPF(VS2013)。我的大多数Windows开发都在VC ++ / MFC中。我试图坚持MVVM模式,并正在编写一些概念验证应用程序来让我的脚湿透。到目前为止,我有一个棘手的问题。

当我的应用程序启动时,它将显示客户和账单的树状视图。我使用一个简单的分层数据模板,每个级别绑定到我的本地数据类型(视图模型)。我想要发生的是当选择一个账单时(现在我有一个按钮来按下账单模板)我想要将树视图替换为账单的详细视图(我不希望弹出一个对话框)向上)。 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的目标是在代码中没有任何内容(或尽可能少)。

在我研究的过程中,我正在寻找能够让我沿着正确的道路前进的指针。我此刻有点糊涂。

提前致谢。

1 个答案:

答案 0 :(得分: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>