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 的字段。在xml中:

<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>

当您单击某些列表框时,如果您单击尚未选择的项目,则所选项目不会改变。

4

2 回答 2

2

首先,您应该定义ItemsSource您的,TabItem并且它们也受到约束。然后你可以将它们绑定到你的 ViewModel 中的一个属性。ListBoxViewModelSelectedItem

这是一个代码示例(我懒得创建一个单独的 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;
        }
    }
}

xml:

<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>
于 2012-08-24T11:37:13.667 回答
1

New answer after you edited :

It does not make much sense to bind the same object to the SelectedItem property of two different lists that contain different elements. You have to redesign your application or you may be confronted to many problems due to this strange design in the futur.

Still, you can achieve want you want to do with a little codebehing. When the user clicks on one of your ListBox, you set the selected item of your other listbox to null. Then you will be notified when you re-click on the first listbox since the selection goes from null to something.

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>

codebehind:

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;
        }
    }
}
于 2012-08-27T15:44:42.477 回答