-1

i have a grid,inside that grid there's a stackpanel inside which there is one Checkbox and 2 TextBlocks. The XAML is :

  <Grid x:name="maingrid" >
    <Stackpanel x:name="panel1">
       <Checkbox height="10" width="10"/>
       <Textblock x:name="name1" text="a"/>
       <Textblock x:name="name2" text="b"/>
       <Textblock x:name="name3" text="c"/>
     </Stackpanel>
   </Grid>

Now, the thing is, inside MainGrid, I am dynamically adding panel1 (the stackpanel) based on a list of random text. Anyway, what i want is , when i check the checkbox, the releavent Stackpanel(panel1)'s textblock values(name1,name2,name3's values) would be passed to a List(Of string) from where I can get the values of the three textblocks of each checked Checkboxes in stackpanels... Somewhat like the DataGrid/DataGridView (winforms) ..

I beg your pardon if I failed to describe my wants properly but I hope you can understand what I'm looking for. I found this but as my motive and situation is entirely different, i can't really make use of the answer in that post... Any help/explanation of my idea ?

UPDATE : A more logical/better explanation If i have a UserControl with 1 checkbox and 2 textblocks and populate a Window's grid with the usercontrol based on datarows derived from a datatable, how do i get the textblock values of the checked checkboxes of the UserControl?

  • The question is unclear. You wrote "dynamically adding", but posted XAML, that contains stack panel. Do you want to insert number of `StackPanel`s inside grid, or there will always be a single one? If answer is "several", will `StackPanel`s content be the same, or the number of `TextBlock`s can vary? Can user check multiple checkboxes? – Dennis Feb 28 '18 at 08:32
  • yes...i want to add multiple stackpanels inside `MianGrid` and the stackpanels content will be the same (1 checkbox and 2 textblocks) and yes, user can check multiple chekcboxes –  Feb 28 '18 at 08:41
  • why not use `DataGrid` instead? [DataGrid+DataTable example](https://stackoverflow.com/a/44206066/1506454) – ASh Feb 28 '18 at 08:53
  • i agree with u but i asked a question yesterday on how to bind data to datagrid in wpf from access database but got no answers....So i thought of making one my own .... –  Feb 28 '18 at 08:55
  • @F.raiyan, you should have done a better research – ASh Feb 28 '18 at 08:57
  • Easy @ASh, I see he did nothing wrong. – Red Wei Feb 28 '18 at 08:59
  • @RedWei, you just can't see deleted questions – ASh Feb 28 '18 at 09:00
  • Pardon if i asked the question in the wrong manner..Did i fail to explain my problem ? –  Feb 28 '18 at 09:01
  • my yseterday's qustion is [here](https://stackoverflow.com/questions/49011951/bind-observeable-collection-to-database-datatable-and-datagrid-to-observeablecol) –  Feb 28 '18 at 09:02
  • @F.raiyan you want to do this with MVVM or no MVVM. – Red Wei Feb 28 '18 at 09:04
  • actually i never used MVVM before,i am really new to WPF and these `model/viewmodel` stuff....I'ld rather stick to NO MVVM way only if u r kind enough to help me –  Feb 28 '18 at 09:06
  • ow and one more thing,as i mentioned about a `Checkbox` in my post, the template of the checkbox is customized , will be able to apply that template/style to the datagrid's checkboxes as well ? –  Feb 28 '18 at 09:09
  • Yes, you will be able to apply that style. I am writing the answer. – Red Wei Feb 28 '18 at 09:19
  • thank u soo much for your patience.. It's a pleasure .. –  Feb 28 '18 at 09:21

2 Answers2

0

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.

Dennis
  • 37,026
  • 10
  • 82
  • 150
  • I know almost nothing about MVVM , so a basic qs: Do i need to create a new project for this ? How do i really get started ? –  Feb 28 '18 at 09:28
  • I found [this](https://www.codeproject.com/Articles/819294/WPF-MVVM-step-by-step-Basics-to-Advance-Level) and i'm starting to learn MVVM...after understanding the basics , i'll implement ur result –  Feb 28 '18 at 09:30
  • You can copy/paste this code to a new WpfApplication project and play with it. In fact, I did the same. Don't be afraid of MVVM - it's not so hard to learn. – Dennis Feb 28 '18 at 09:31
  • Can i use it in the existing project ? –  Feb 28 '18 at 09:31
  • Of course you can. But you will need to adapt it to your current code. – Dennis Feb 28 '18 at 09:34
  • can u review the other answer ? Which method should i go with ? Yours or the other guys answer? –  Feb 28 '18 at 09:36
  • i posted my yesterday's question on MSDN and someone there said that my biggest issue is that i am using an ACCESS database..any comments on this ? –  Feb 28 '18 at 09:37
  • The choice is yours. My answer relies on rather complex WPF production code. I don't recommend to go that way (I mean the second answer). – Dennis Feb 28 '18 at 09:38
  • To be honest, you should learn MVVM and adapt it into your WPF program. This will take some times to practise before you can adapt it properly and easily. So if you need your program ugently, just go for my answer, if it is not, start to learn MVVM. I can help you to learn MVVM, just send me inbox of your Discord. – Red Wei Feb 28 '18 at 09:43
  • can u start a chat with me > –  Feb 28 '18 at 09:47
  • Please go to my profile, you will see my email here. Send me an email. – Red Wei Feb 28 '18 at 09:52
  • i eamiled u,please see it –  Feb 28 '18 at 09:55
0

Non-MVVM way

To access your value inside your customized UserControl. You need a UserControl with a name on every control in it and then when you use, you just call it's name.

In MyUserControl.xaml:

<Stackpanel x:name="panel1">
   <Checkbox x:name="checkbox1" height="10" width="10"/> <!-- Apply your style here -->
   <Textblock x:name="name1" text="a"/>
   <Textblock x:name="name2" text="b"/>
   <Textblock x:name="name3" text="c"/>
</Stackpanel>

In MyWindow.xaml:

<local:MyUserControl x:Name="myUserControlInstance"/>
<Button Content="Click me" Click="Button_Click" />

In MyWindow.cs:

    private void Button_Click(object sender, RoutedEventArgs e) 
    {
        if (myUserControlInstance.checkbox1.IsChecked.HasValue)
        {
             var checkboxValue=myUserControlInstance.checkbox1.IsChecked.Value;
        }
    }
Red Wei
  • 854
  • 6
  • 22
  • if i have multiple useontrols and multiple checked checkboxes,will be able to loop through them ? –  Feb 28 '18 at 09:43
  • Solution 1: You just need to name every UserControl you have added and loop though that name list. Solution 2: You need to loop on every UserControl without it's name. – Red Wei Feb 28 '18 at 09:45
  • How can i name every usecontrol as i'm adding them dynamically based on datarows from a datatable ? –  Feb 28 '18 at 09:46