2012-08-24 52 views
0

我有一些领域视图模型,即 如何绑在一个视图模型

 
type ViewModel = 
    member x.a = [1;2;3] 
    member x.b = [4;5;6] 
    member x.c = [7] 

,并在WPF应用程序中的一些控件放置一些看法,如:

<Control.Resources> 
        <DataTemplate x:Key="ItemTempl"> 
         <TextBlock Text="{Binding}" /> 
        </DataTemplate> 

        <DataTemplate x:Key="SomeTempl"> 
         <ListBox ItemsSource="{Binding}" 
           ItemTemplate="{StaticResource ItemTempl}" /> 
        </DataTemplate> 
       </Control.Resources> 

       <StackPanel> 
        <TabControl x:Name="ListBoxViewPresenter"> 
         <TabItem Header="vm.a" Content="{Binding vm.a}" 
          ContentTemplate="{StaticResource SomeTempl}"/> 
         <TabItem Header="vm.b" Content="{Binding vm.b}" 
          ContentTemplate="{StaticResource SomeTempl}"/> 
         <TabItem Header="vm.c" Content="{Binding vm.c}" 
          ContentTemplate="{StaticResource SomeTempl}"/> 
        </TabControl> 
        <ListBox x:Name="ListBoxViewPresenter"> 
         <ListBoxItem Content="{Binding vm.a}" 
            ContentTemplate="{StaticResource SomeTempl}" /> 
         <ListBoxItem Content="{Binding vm.b}" 
            ContentTemplate="{StaticResource SomeTempl}" /> 
         <ListBoxItem Content="{Binding vm.c}" 
            ContentTemplate="{StaticResource SomeTempl}" /> 
        </ListBox> 
       </StackPanel> 

我应该怎么办要实现这样的行为: 当您单击ListBoxViewPresenter中的vm.a/b/c中的某个元素时,必须在相应的TabItem中选择ListBoxViewPresenter中的相同元素。

UPD: 具体来说,我真正的问题,从原点主题改变。

我有ViewModel的字段:onelines,twolines ...和一个名为selected_scheme的字段。 在XAML:

<TreeViewItem Header="{Binding Path=name}" x:Name="ProjectArea"> 
        <TreeViewItem Header="Однониточные планы" Style="{StaticResource MyTreeViewItem}"> 
         <ContentPresenter Content="{Binding onelines}" ContentTemplate="{StaticResource SchemeWrapperTemplate}" /> 
        </TreeViewItem> 
        <TreeViewItem Header="Двухниточные планы" Style="{StaticResource MyTreeViewItem}"> 
         <ContentPresenter Content="{Binding twolines}" ContentTemplate="{StaticResource SchemeWrapperTemplate}" /> 
        </TreeViewItem> 

和数据模板:

  <DataTemplate x:Key="SchemeWrapperTemplate"> 
      <ListBox ItemsSource="{Binding schemes}" 
        ItemTemplate="{StaticResource SchemeTemplate}" 
        SelectedItem="{Binding selected_scheme}"> 
       <ListBox.Style> 

在其他地方的程序:

<Grid Grid.Row="1"> 
        <TextBlock Text="{Binding selected_scheme.path}" /> 
       </Grid> 

当你点击一些列表框,如果你再选择的项目不改变点击一个SelectedItems。

+0

我不明白这一点..在 “所选项目” 并没有改变,但为什么会改变?它应该已经等于ListBox的SelectedItem,因为它绑定了它? – franssu

+0

selected_item字段是所有ListBox的字段之一。在我的代码中,您可以看到两个在模板“SchemeWrapperTemplate” - Content =“{Binding onelines}”和Content =“{Binding twolines}”上构建的ListBoxes。当我点击第一个列表框中的某个元素时,selected_item发生了变化,然后我点击第二个列表框中的某个元素,而selected_item也发生了变化,但是当它在第一个列表框中点击已经选择的项目时 - 没有任何变化。它期望但我不想跟踪活动的ListBox。有更容易的方法吗? – psct

+0

一个更简单的方法来做什么?你想要达到什么目的?你只是想在用户点击一个项目时得到通知? – franssu

回答

1

您编辑后的新的答案:

它确实没有将同一对象绑定到包含不同元素的两个不同列表的SelectedItem属性上意义重大。你必须重新设计你的应用程序,否则你可能会遇到很多问题,因为这个奇怪的设计在未来。

尽管如此,你仍然可以通过一点点代码实现想要的目标。当用户单击某个ListBox时,将其他列表框的选定项目设置为null。然后,当你重新点击第一个列表框时,你会收到通知,因为选择从空到某些东西。

XAML:

<Window x:Class="WpfApplication13.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <StackPanel> 
      <ListBox x:Name="ListBoxViewPresenter" 
        SelectedItem="{Binding CurrentlySelectedItem}" 
        ItemsSource="{Binding MyItemsSource}" /> 
      <ListBox x:Name="ListBoxViewPresenter2" 
        SelectedItem="{Binding CurrentlySelectedItem}" 
        ItemsSource="{Binding MyItemsSource2}" /> 
     </StackPanel> 
    </Grid> 
</Window> 

代码隐藏:

using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Input; 
using System.ComponentModel; 

namespace WpfApplication13 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     #region INotifyPropertyChanged Members 

     public event PropertyChangedEventHandler PropertyChanged; 

     #endregion 

     private object _currentlySelectedItem; 

     public object CurrentlySelectedItem 
     { 
      get { return _currentlySelectedItem; } 

      set 
      { 
       _currentlySelectedItem = value; 

       if (this.PropertyChanged != null) 
       { 
        this.PropertyChanged(this, new PropertyChangedEventArgs("CurrentlySelectedItem")); 
       } 
      } 
     } 

     private List<int> _myItemsSource = new List<int> { 1, 2 }; 

     private List<int> _myItemsSource2 = new List<int> { 3, 4 }; 

     public List<int> MyItemsSource 
     { 
      get { return _myItemsSource; } 
      set { _myItemsSource = value; } 
     } 


     public List<int> MyItemsSource2 
     { 
      get { return _myItemsSource2; } 
      set { _myItemsSource2 = value; } 
     } 

     public MainWindow() 
     { 
      InitializeComponent(); 

      this.DataContext = this; 

      ListBoxViewPresenter.PreviewMouseDown += ListBoxViewPresenter_PreviewMouseDown; 
      ListBoxViewPresenter2.PreviewMouseDown += ListBoxViewPresenter2_PreviewMouseDown; 
     } 

     void ListBoxViewPresenter_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
     { 
      ListBoxViewPresenter2.SelectedItem = null; 
     } 

     void ListBoxViewPresenter2_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
     { 
      ListBoxViewPresenter.SelectedItem = null; 
     } 
    } 
} 
+0

我通过将ListBoxItem的模板从简单的TextBlock更改为Button,并将ListBoxItem的数据上下文作为参数并将其设置为ViewModel的selected_item,从而解决了此问题。 – psct

2

首先,您应该在ViewModel中定义您的TabItemListBoxItemsSource,它们也绑定。 然后,您可以将其SelectedItem绑定到ViewModel中的属性。

下面是一个代码示例(我是懒得来创建一个单独的ViewModel类,因此它与我的主窗口类混合,但你的想法...):

代码隐藏:

namespace WpfApplication13 
{ 
    public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     private object _currentlySelectedItem; 

     public object CurrentlySelectedItem 
     { 
      get { return _currentlySelectedItem; } 

      set 
      { 
       _currentlySelectedItem = value; 

       if (this.PropertyChanged != null) 
       { 
        this.PropertyChanged(this, new PropertyChangedEventArgs("CurrentlySelectedItem")); 
       } 
      } 
     } 

     public class MyClass 
     { 
      public string MyString { get; set; } 

      public MyClass(string myString) 
      { 
       this.MyString = myString; 
      } 
     } 

     private List<MyClass> _myItemsSource = new List<MyClass> 
               { 
                new MyClass("toto"), 
                new MyClass("tata") 
               }; 

     public List<MyClass> MyItemsSource 
     { 
      get { return _myItemsSource; } 
      set { _myItemsSource = value; } 
     } 

     public object A 
     { 
      get { return "toto"; } 
     } 

     public object B 
     { 
      get { return "tata"; } 
     } 

     public MainWindow() 
     { 
      InitializeComponent(); 

      this.DataContext = this; 
     } 
    } 
} 

XAML:

<Window x:Class="WpfApplication13.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <StackPanel> 
      <TabControl x:Name="ListBoxViewPresenter" 
         SelectedItem="{Binding CurrentlySelectedItem}" 
         ItemsSource="{Binding MyItemsSource}" /> 
      <ListBox x:Name="ListBoxViewPresenter2" 
        SelectedItem="{Binding CurrentlySelectedItem}" 
        ItemsSource="{Binding MyItemsSource}" /> 
     </StackPanel> 
    </Grid> 
</Window> 
+0

有没有办法做到这一点,而不设置ItemsSource? – psct

+0

@psct是的,您可以使用ListBoxViewPresenter2.Items.Add()手动添加或删除代码隐藏项中的项目,但除非您有足够的理由这样做,否则我强烈建议使用ItemsSource。 – franssu

+0

好吧,事实证明我的问题没有解决这个问题。我有一些ListBox与ViewModel中的一些列表的绑定,当他们的项目之一选择我希望改变我的ViewModel“selected_item”字段。但是,如果在一个名为A的ListBox中选择一个字段,那么在其他ListBox中执行相同的操作,然后在ListBox中“A”单击尚未选择的项目。现在SelectedItem不会更改,而“selected_item”不会更改。 – psct

相关问题