Click here to Skip to main content
15,892,072 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
hi...
i have 4 checkbox and 1 textbox...
when i select value from checkbox...those value has to be bind to textbox...
Means when i select 2 checkbox...content of each checkbox has to get binded to textbox..
i done it... but when i select checkbox getting error saying that null reference..
how to solve this problem...

What I have tried:

In view :
XML
<Window x:Class="multichkboxsel.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:multichkboxsel"
        xmlns:viewmodel="clr-namespace:multichkboxsel.ViewModel"
        xmlns:converter="clr-namespace:multichkboxsel.converter"
        xmlns:view="clr-namespace:multichkboxsel.View"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
       
        <Window.Resources>
        <viewmodel:chkviewmdl x:Key="vm"></viewmodel:chkviewmdl>
        <converter:myconverter x:Key="cv"></converter:myconverter>
        </Window.Resources>
        <StackPanel Orientation="Vertical" Margin="20" DataContext="{Binding Source={StaticResource vm}}">
            <CheckBox Width="120" Name="cbIndia" Content="India" Command="{Binding MyCommand}">
                <CheckBox.CommandParameter>
                    <MultiBinding Converter="{StaticResource cv}">
                        <Binding ElementName="cbIndia" Path="Content"/>
                        <Binding ElementName="cbIndia" Path="IsChecked"/>
                    </MultiBinding>
                </CheckBox.CommandParameter>
            </CheckBox>
            <CheckBox Width="120" Name="cbUS" Content="US" Command="{Binding MyCommand}">
                <CheckBox.CommandParameter>
                    <MultiBinding Converter="{StaticResource cv}">
                        <Binding ElementName="cbUS" Path="Content"/>
                        <Binding ElementName="cbUS" Path="IsChecked"/>
                    </MultiBinding>
                </CheckBox.CommandParameter>
            </CheckBox>
            <CheckBox Width="120" Name="cbUK" Content="UK" Command="{Binding MyCommand}">
                <CheckBox.CommandParameter>
                    <MultiBinding Converter="{StaticResource cv}">
                        <Binding ElementName="cbUK" Path="Content"/>
                        <Binding ElementName="cbUK" Path="IsChecked"/>
                    </MultiBinding>
                </CheckBox.CommandParameter>
            </CheckBox>
            <CheckBox Width="120" Name="cbChina" Content="China" Command="{Binding MyCommand}">
                <CheckBox.CommandParameter>
                    <MultiBinding Converter="{StaticResource cv}">
                        <Binding ElementName="cbChina" Path="Content"/>
                        <Binding ElementName="cbChina" Path="IsChecked"/>
                    </MultiBinding>
                </CheckBox.CommandParameter>
            </CheckBox>
            <TextBox Width="300" Margin="20" Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
        </StackPanel>
    </Window>  

In viewmodel:
C#
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace multichkboxsel.ViewModel
{
    class chkviewmdl : INotifyPropertyChanged
    {

        private ObservableCollection<string> _countries;
        public ObservableCollection<string> Countries
        {
            get { return _countries; ; }
            set
            {
                _countries = value;
                OnPropertyChange("Countries");
            }
        }
        public ICommand MyCommand { get; set; }
        public chkviewmdl()
        {
            MyCommand = new RelayCommand(executemethod, canexecutemethod);
        }

        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                OnPropertyChange("Name");
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChange(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
            }
        }

        private bool canexecutemethod(object parameter)
        {
            return true;
        }

        private void executemethod(object parameter)
        {
            //Name = (string)parameter;
            var values = (object[])parameter;
        
            string name = (string)values[0];
            bool check = (bool)values[1];
            if (check)
            {
                Countries.Add(name);
            }
            else
            {
                Countries.Remove(name);
            }

            Name = "";
            foreach (string item in Countries)
            {
                Name = Name + item;
            }

        }

    }
}

AND I USED CONVERTER CLASS ALSO...
Posted
Updated 30-Aug-17 16:27pm
v2
Comments
Graeme_Grant 30-Aug-17 10:20am    
Sounds like the error is in the converter class (no code available). Set a breakpoint in the converter class and step through the code...

1 solution

You're making a lot of work for yourself. You need to simplify your code. Here is an example for you:

1. First, sperate the INotifyPropertyChanged into a reusable base class:
C#
public abstract class ObservableBase : INotifyPropertyChanged
{
    public void Set<TValue>(ref TValue field, TValue newValue,
                            [CallerMemberName] string propertyName = "")
    {
        if (EqualityComparer<TValue>.Default.Equals(field, default(TValue))
            || !field.Equals(newValue))
        {
            field = newValue;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

2. Next, lets encapsulate ueach country into its own model:
C#
public class CountryModel : ObservableBase
{
    private bool isChecked;
    public bool IsChecked
    {
        get { return isChecked; }
        set { Set(ref isChecked, value); }
    }

    private string name;
    public string Name
    {
        get { return name; }
        set { Set(ref name, value); }
    }
}

3. Now lets include the collection of countries into our ViewModel:
C#
public class MainViewModel : ObservableBase
{
    public ObservableCollection<CountryModel> Countries { get; set; } = new ObservableCollection<CountryModel>
    {
        new CountryModel { Name = "India", IsChecked = true },
        new CountryModel { Name = "US" },
        new CountryModel { Name = "UK" },
        new CountryModel { Name = "China" }
    };
}

4. Lastly, time to do the UI: Show the list of selectable countries to the User. I have also added a list of selected countries that reflects the changes made by the user:

4a. XAML Page:
XML
<Window
    x:Class="MultiSelectCheckList.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    mc:Ignorable="d"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    xmlns:clr="clr-namespace:System;assembly=mscorlib"
    xmlns:local="clr-namespace:MultiSelectCheckList"

    Title="CodeProject - MultiSelect CheckboxList"
    Height="350" Width="525" WindowStartupLocation="CenterScreen">

    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>

    <Window.Resources>

        <CollectionViewSource x:Key="SelectedCountries" Source="{Binding Countries}"
                              IsLiveFilteringRequested="True"
                              Filter="CollectionViewSource_Filter">
            <CollectionViewSource.LiveFilteringProperties>
                <clr:String>IsChecked</clr:String>
            </CollectionViewSource.LiveFilteringProperties>
        </CollectionViewSource>

    </Window.Resources>

    <Grid Margin="20">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <ItemsControl x:Name="Selection" ItemsSource="{Binding Countries}"
                      BorderThickness="1" BorderBrush="Silver">
            <ItemsControl.Resources>
                <DataTemplate DataType="{x:Type local:CountryModel}">
                    <CheckBox Content="{Binding Name}"
                              IsChecked="{Binding IsChecked, Mode=TwoWay}"
                              Margin="10"/>
                </DataTemplate>
            </ItemsControl.Resources>
        </ItemsControl>

        <ListBox Grid.Column="1" Margin="10 0 0 0"
                 ItemsSource="{Binding Source={StaticResource SelectedCountries}}">
            <ListBox.Resources>
                <DataTemplate DataType="{x:Type local:CountryModel}">
                    <TextBlock Text="{Binding Name}" Margin="10"/>
                </DataTemplate>
            </ListBox.Resources>
        </ListBox>
    </Grid>

</Window>

4b. Code-behind for the CollectionViewSource filter:
C#
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
    {
        e.Accepted = (e.Item as CountryModel).IsChecked;
    }
}

Now, the list of countries is easily expandable without any changes to the XAML code.
 
Share this answer
 
Comments
Member 12938297 31-Aug-17 2:45am    
Thank you..

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900