单独 windows 中不同控件的 wpf 绑定同步
wpf binding synchronization across different controls in separate windows
我有三个 windows,我需要在其中同步一个值。
我需要在三个 windows 中更新所选项目。其中两个包含一个组合框,主要 window 包含一个标签。因此,我需要两个组合框相同,并且标签会更新以反映组合框中的所选项目。
目前我同步了两个组合,但我的问题是如何同步标签。我试过使用 Properties、DependencyProperties、Implementing 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>
new CollectionView() 导致 Visual Studio 2017 在调试输出中输出:
System.Windows.Data Warning: 53 : Using CollectionView directly is not
fully supported. The basic features work, although with some
inefficiencies, but advanced features may encounter known bugs.
Consider using a derived class to avoid these problems.
相反,我将其更改为键入 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);
}
}
我有三个 windows,我需要在其中同步一个值。 我需要在三个 windows 中更新所选项目。其中两个包含一个组合框,主要 window 包含一个标签。因此,我需要两个组合框相同,并且标签会更新以反映组合框中的所选项目。
目前我同步了两个组合,但我的问题是如何同步标签。我试过使用 Properties、DependencyProperties、Implementing 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>
new CollectionView() 导致 Visual Studio 2017 在调试输出中输出:
System.Windows.Data Warning: 53 : Using CollectionView directly is not fully supported. The basic features work, although with some inefficiencies, but advanced features may encounter known bugs. Consider using a derived class to avoid these problems.
相反,我将其更改为键入 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);
}
}