【问题标题】:wpf binding synchronization across different controls in separate windows跨不同窗口中不同控件的 wpf 绑定同步
【发布时间】:2019-08-10 09:52:43
【问题描述】:

我有三个窗口,我需要在其中同步单个值。 我需要跨三个窗口更新所选项目。其中两个包含一个组合框和一个包含标签的主窗口。因此,我需要两个组合框相同,并且标签会更新以反映组合框中的选定项目。

目前我同步了这两个组合,但我的问题是如何同步标签。我试过使用属性,使用 DependencyProperties,实现 INotifyPropertyChanged 但标签没有运气

我有这个示例代码无法同步标签:

MainWindow.cs:

public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public CollectionView Items { get; set; }
        private string _selectedItem;
        public event PropertyChangedEventHandler PropertyChanged;
        public string SelectedItem
        {
            get { return (string)GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }

        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register("SelectedItem",
        typeof(string), typeof(MainWindow), new UIPropertyMetadata(""));

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public MainWindow()
        {
            DataContext = this;
            InitializeComponent();
            Left = 100; Width = 350; Height = 200; Top = 10;
            Business business = new Business();
            Items = new CollectionView(business.GetItemsFromWebService());
            Wnd1 wnd1 = new Wnd1();
            wnd1.Left = 100; wnd1.Width = 350; wnd1.Height = 200; wnd1.Top = 210;
            wnd1.Show();

            Wnd2 wnd2 = new Wnd2();
            wnd2.Left = 100; wnd2.Width = 350; wnd2.Height = 200; wnd2.Top = 410;
            wnd2.Show();

            wnd1.cbItems.ItemsSource = Items;
            wnd1.cbItems.SelectedValue = SelectedItem;
            wnd2.cbItems.ItemsSource = Items;
            wnd2.cbItems.SelectedValue = SelectedItem;

            Binding labelBinding = new Binding();
            labelBinding.Mode = BindingMode.TwoWay;
            labelBinding.Source = SelectedItem;
            labelBinding.Path = new PropertyPath("SelectedItem");
            lbSelected.SetBinding(Label.ContentProperty, labelBinding);

            Binding cmbBindingW1 = new Binding();
            cmbBindingW1.Mode = BindingMode.TwoWay;
            cmbBindingW1.Source = SelectedItem;
            cmbBindingW1.Path = new PropertyPath("SelectedItem");
            wnd1.cbItems.SetBinding(ComboBox.SelectedItemProperty, cmbBindingW1);
            wnd1.cbItems.SelectionChanged += CbItems_SelectionChanged;

            Binding cmbBindingW2 = new Binding();
            cmbBindingW2.Mode = BindingMode.TwoWay;
            cmbBindingW2.Source = SelectedItem;
            cmbBindingW2.Path = new PropertyPath("SelectedItem");
            wnd1.cbItems.SetBinding(ComboBox.SelectedItemProperty, cmbBindingW2);
        }

        private void CbItems_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            int a = 0;
            SelectedItem = ((ComboBox)sender).SelectedItem.ToString();
        }
    }

MainWindow.xaml:

<Window x:Class="DropDownSync.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DropDownSync"
        mc:Ignorable="d"
        Title="MainWindow" Height="183.333" Width="376.667"
        Name="wMain">
    <Grid>
        <Label Name="lbSelected" HorizontalAlignment="Left" Margin="10,71,0,0" VerticalAlignment="Top" Width="80"
               Visibility="Visible"/>
    </Grid>
</Window>

Business.cs:

public class Business
    {
        public List<string> GetItemsFromWebService()
        {
            List<string> result = new List<string>();
            result.Add("item1");                
            result.Add("item2");
            result.Add("item3");
            return result;
        }
    }

Wnd1.xaml:

<Window x:Class="DropDownSync.Wnd1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DropDownSync"
        mc:Ignorable="d"
        Title="Wnd1" Height="211.667" Width="518.333"
        Name="w1">
    <Grid>
        <ComboBox Name="cbItems" HorizontalAlignment="Left" Margin="90,14,0,0" VerticalAlignment="Top" Width="120"/>
        <Label Content="Current item" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="80"/>
    </Grid>
</Window>

Wnd2.xaml:

<Window x:Class="DropDownSync.Wnd2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DropDownSync"
        mc:Ignorable="d"
        Title="Wnd2" Height="190" Width="453.333"
        Name="w2">
    <Grid>
        <ComboBox Name="cbItems" HorizontalAlignment="Left" Margin="90,14,0,0" VerticalAlignment="Top" Width="120"/>
        <Label Content="Current item" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="80"/>
    </Grid>
</Window>

【问题讨论】:

    标签: wpf binding dependency-properties code-behind


    【解决方案1】:

    new CollectionView() 导致 Visual Studio 2017 在调试输出中输出:

    System.Windows.Data 警告:53:不能直接使用 CollectionView 完全支持。基本功能有效,尽管有一些 效率低下,但高级功能可能会遇到已知错误。 考虑使用派生类来避免这些问题。

    相反,我将其更改为输入 ICollectionView,然后将 Items 设置为 CollectionViewSource.GetDefaultView(business.GetItemsFromWebService());

    另外,您设置了两次 wnd1.cbItems.Binding(ComboBox.SelectedItemProperty, xxx)。我假设第二个应该是 wnd2。

    如果绑定正确,则不需要 SelectionChanged 事件处理程序。

    这里是更新后的 MainWindow.cs 更改:

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public ICollectionView Items { get; set; }
    
        public event PropertyChangedEventHandler PropertyChanged;
        public string SelectedItem
        {
            get { return (string)GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }
    
        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register("SelectedItem",
        typeof(string), typeof(MainWindow), new UIPropertyMetadata(""));
    
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        public MainWindow()
        {
            DataContext = this;
            InitializeComponent();
            Left = 100; Width = 350; Height = 200; Top = 10;
            Business business = new Business();
            Items = CollectionViewSource.GetDefaultView(business.GetItemsFromWebService());
    
            Wnd1 wnd1 = new Wnd1();
            wnd1.Left = 100; wnd1.Width = 350; wnd1.Height = 200; wnd1.Top = 210;
            wnd1.Show();
    
            Wnd2 wnd2 = new Wnd2();
            wnd2.Left = 100; wnd2.Width = 350; wnd2.Height = 200; wnd2.Top = 410;
            wnd2.Show();
    
            wnd1.cbItems.ItemsSource = Items;
            wnd2.cbItems.ItemsSource = Items;
    
            Binding labelBinding = new Binding();
            labelBinding.Mode = BindingMode.TwoWay;
            labelBinding.Source = this;
            labelBinding.Path = new PropertyPath("SelectedItem");
    
            // no need to make an identical bindings, just use the same one again
            lbSelected.SetBinding(Label.ContentProperty, labelBinding);
            wnd1.cbItems.SetBinding(ComboBox.SelectedItemProperty, labelBinding);
            wnd2.cbItems.SetBinding(ComboBox.SelectedItemProperty, labelBinding);
        }
    }
    

    【讨论】:

    • 非常感谢。它以这种方式工作。但是,我仍然想知道绑定不起作用的原因。这是由于 ICollectionView 或 xxx.Source 未正确定义所致。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-16
    • 2021-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多