Zoya Sheikh
Zoya Sheikh

Reputation: 939

How to bind Selected Items in MVVM

I am using WPF, MVVM and DevExpress GridControl. There are two panels in my MainWindow.xaml. Panle1 has Grid and Panel2 has Textbox. I want that if i select an item from Grid in Panel1 it's name should display in that Panle2 Textbox. Iwrote Code but it is not working. Can you Please help me to solve this?

*In NameModel From Models Folder I wrote:*

private NameModelClass _selectedCustomer;
public NameModelClass SelectedCustomer
{
    get { return _selectedCustomer; }
    set
    {
        if (_selectedCustomer != value)
        {
            _selectedCustomer = value;
            LastName = value.LastName;
            OnPropertyChanged("SelectedCustomer");
        }
     }

    public List<Namess> ListPerson { get; set; }

    void CreateList()
    {
        ListPerson = new List<Namess>();
        for (int i = 0; i < 10; i++)
        {
            ListPerson.Add(new Namess(i));
        }
    }

    public class Namess
    {
        public Namess(int i)
        {
            FirstName = "FirstName" + i;
            LastName = "LastName" + i;
            Age = i * 10;
        }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
    }
}

In MianWindow.xaml I wrote:

<dxdo:LayoutPanel Caption="Grid" Caption="Panel1" x:Name="abc1">
    <Grid>
        <dxg:GridControl x:Name="grid" Height="233" ItemsSource="{Binding ListPerson}" AutoGenerateColumns="AddNew" HorizontalAlignment="Left" VerticalAlignment="Top"   SelectedItem="{Binding SelectedNames}">
            <dxg:GridControl.View>
                <dxg:TableView ShowTotalSummary="True"/>
            </dxg:GridControl.View>
        </dxg:GridControl>
    </Grid>
</dxdo:LayoutPanel>

<dxdo:LayoutPanel Caption="Panel2" x:Name="abc1">
    <TextBox Width="166" Background="White" Height="33"  HorizontalAlignment="Right"  VerticalAlignment="Bottom"  Text="{Binding Path=LastName}"/>
</dxdo:LayoutPanel>

I am new to MVVM and c#. I f my query is not clear to you please ask me. Thank you.

Upvotes: 1

Views: 3910

Answers (3)

Carles Company
Carles Company

Reputation: 7216

I do it this way:

private Namess _selectedCustomer;
public Namess SelectedCustomer
{
    get { return _selectedCustomer; }
    set
    {
        if (_selectedCustomer != value)
        {
            _selectedCustomer = value;
            OnPropertyChanged("SelectedCustomer");
        }
     }

    public List<Namess> ListPerson { get; set; }

    void CreateList()
    {
        ListPerson = new List<Namess>();
        for (int i = 0; i < 10; i++)
        {
            ListPerson.Add(new Namess(i));
        }
    }

    public class Namess : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }

        public Namess(int i)
        {
            FirstName = "FirstName" + i;
            LastName = "LastName" + i;
            Age = i * 10;
        }
        public string FirstName { get; set; }
        private string _lastName;
        public string LastName 
        { 
            get
            {
                return _lastName;
            }
            set
            {
                if(value==_lastName)
                    return;
                _lastName=value;
                OnPropertyChanged("LastName");
            }
        }
        public int Age { get; set; }
    }
}

and in your view:

<dxdo:LayoutPanel Caption="Grid" Caption="Panel1" x:Name="abc1">
    <Grid>
        <dxg:GridControl x:Name="grid" Height="233" ItemsSource="{Binding ListPerson}" AutoGenerateColumns="AddNew" HorizontalAlignment="Left" VerticalAlignment="Top" SelectedItem="{Binding SelectedNames,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
            <dxg:GridControl.View>
                <dxg:TableView ShowTotalSummary="True"/>
            </dxg:GridControl.View>
        </dxg:GridControl>
    </Grid>
</dxdo:LayoutPanel>

<dxdo:LayoutPanel Caption="Panel2" x:Name="abc1">
    <TextBox Width="166" Background="White" Height="33"  HorizontalAlignment="Right" VerticalAlignment="Bottom"  Text="{Binding Path=SelectedCustomer.LastName,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
</dxdo:LayoutPanel>

Bsically I changed the type of SelectedCustomer to one of the collection of items. In the view you can set the binding of your TextBox directly to a property of the SelectedCustomer.

Upvotes: 1

BaconSah
BaconSah

Reputation: 421

Have you tried:

SelectedItem="{Binding SelectedNames, Mode=TwoWay}"

After looking at it more, your main Namess Class could do with implementing INotifyPropertyChanged

With each property raising the property changed event when it ahem changes.

Also using an observable collection so when you add and remove items it also raises changes.

That way, the notification change system receives the notify of property changes to change the view accordingly via bindings.

Upvotes: 0

Rachael
Rachael

Reputation: 1995

It looks like you forgot to raise the INPC (INotifyPropertyChanged) event for the "LastName" string.

So try this (changed is in the setter below):

public NameModelClass SelectedCustomer
    {
    get { return _selectedCustomer; }
    set
        {
        if (_selectedCustomer != value)
            {
            _selectedCustomer = value;
            LastName = value.LastName;
            OnPropertyChanged("SelectedCustomer");
            OnPropertyChanged("LastName");   //<-- new 
            }
        }
    }

You have to send out INPCs so that the binding knows to update to the new value. The displayed binding won't "grab" the new value for LastName unles you raise that event.

Upvotes: 0

Related Questions