Don't try to work with XAML as you worked with WinForms. It's a dead-end.
Use MVVM, data binding, and work with data first of all.
Here's sample view model for "stack panel"s and their content:
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
is a basic INotifyPropertyChanged
implementation (google it).
Next, view model for sample application:
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. Note, that you don't need Grid
, use ItemsControl
instead:
<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>
Code-behind for 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" },
}
};
}
}
In case of UserControl
you must to provide appropriate properties from your control to bind to, and change ItemTemplate
.