不要像使用 WinForms 一样尝试使用 XAML。这是一个死胡同。
首先使用 MVVM、数据绑定和处理数据。
这是“堆栈面板”及其内容的示例视图模型:
public sealed class ItemViewModel : ViewModelBase
{
private bool isChecked;
public bool IsChecked
{
get { return isChecked; }
set
{
if (isChecked != value)
{
isChecked = value;
OnPropertyChanged();
}
}
}
public string Name1 { get; set; }
public string Name2 { get; set; }
}
ViewModelBase 是一个基本的INotifyPropertyChanged 实现(google it)。
接下来,查看示例应用程序的模型:
public sealed class MainViewModel
{
private ObservableCollection<ItemViewModel> items;
public ObservableCollection<ItemViewModel> Items
{
get
{
if (items == null)
{
items = new ObservableCollection<ItemViewModel>();
items.CollectionChanged += ItemsCollectionChanged;
}
return items;
}
}
private void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
// we want to be notified, if IsChecked is changed;
// ObservableCollection<T> adds one item per time, so, we just using NewItems[0]
((ItemViewModel)e.NewItems[0]).PropertyChanged += ItemPropertyChanged;
break;
case NotifyCollectionChangedAction.Remove:
// we need to unsibscribe, when removing item from collection,
// to avoid memory leak
((ItemViewModel)e.OldItems[0]).PropertyChanged -= ItemPropertyChanged;
break;
}
}
private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// we're interested only in IsCheckedProperty
if (e.PropertyName == nameof(ItemViewModel.IsChecked))
{
// let's update our list
UpdateItemTextValues();
}
}
private void UpdateItemTextValues()
{
// retrieving NameN property values from checked items as a single list
var itemTextValues = Items
.Where(_ => _.IsChecked)
.Select(_ => new[]
{
_.Name1,
_.Name2
})
.SelectMany(_ => _)
.ToList();
// do somethig with the list
Trace.WriteLine(null);
foreach (var value in itemTextValues)
{
Trace.WriteLine(value);
}
}
}
XAML。请注意,您不需要Grid,请改用ItemsControl:
<Window x:Class="WpfApplication1.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:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:ItemViewModel}">
<StackPanel>
<CheckBox Content="Check me" IsChecked="{Binding IsChecked}"/>
<TextBlock Text="{Binding Name1}"/>
<TextBlock Text="{Binding Name2}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
MainWindow 的代码隐藏:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel
{
Items =
{
// these are samle items;
// you can fill collection the way you want
new ItemViewModel { Name1 = "A", Name2 = "B" },
new ItemViewModel { Name1 = "C", Name2 = "D" },
new ItemViewModel { Name1 = "E", Name2 = "F" },
}
};
}
}
如果是UserControl,您必须从您的控件中提供适当的属性以绑定到ItemTemplate,并更改ItemTemplate。