locked
Update textbox based on combobox selection in MVVM RRS feed

  • Question

  • Hi,

    I have a View with combobox and some textboxes, which is responsible to add new Customer record.  When the View is displayed, the combobox displays of existing customers.  If user selects one from combobox I want the values displayed to textboxes.  User can choose to enter data manually without using combobox.

    My question is how can I update textboxes based on combobox selection in MVVM?  I can do this in Form's by manually updating the textboxes but in MVVM.

    I am not asking for the detailed solution, but the general solution would be much appreciated, like do I need to update relevant Properties in ViewModel? If so what is the best approach?

    Thanks 

    Wednesday, July 3, 2013 7:14 PM

Answers

  • Hi,

    I have a View with combobox and some textboxes, which is responsible to add new Customer record.  When the View is displayed, the combobox displays of existing customers.  If user selects one from combobox I want the values displayed to textboxes.  User can choose to enter data manually without using combobox.

    My question is how can I update textboxes based on combobox selection in MVVM?  I can do this in Form's by manually updating the textboxes but in MVVM.

    I am not asking for the detailed solution, but the general solution would be much appreciated, like do I need to update relevant Properties in ViewModel? If so what is the best approach?

    Thanks 

    If your ComboBox displays Customers, your should bind the SelectedItem property to a property of type Customer of your view model:

    <ComboBox ItemsSource="{Binding Customers}" SelectedItem="{Binding SelectedCustomers}" DisplayMemberPath="Name"/>

    You then raise the PropertyChanged event in the setter of the property in the view model:

    private Customer _selectedCustomer;
            public Customer SelectedCustomer
            {
                get { return _selectedCustomer; }
                set { selectedCustomer = value; OnPropertyChanged("SelectedCustomer"); }
            }

    ..and bind the TextBox to a property of the SelectedCustomer object:

    <TextBlock Text="{Binding SelectedCustomer.Name}"/> 
    

    • Marked as answer by Alex Teslin Friday, July 5, 2013 8:24 AM
    Thursday, July 4, 2013 4:06 PM
  • Use another Customer property to bind the TextBoxes to if you don't want to change the property values of the one that is selected in the ComboBox:

            private Customer _selectedCustomer;
            public Customer SelectedCustomer
            {
                get { return _selectedCustomer; }
                set 
                { 
                    _selectedCustomer = value;
                    OnPropertyChanged("SelectedCustomer");
      //set properties of the object that is bound to the TextBoxes
                    _itemInEditMode.Name = _selectedCustomer.Name;
                    OnPropertyChanged("ItemInEditMode");
                }
            }
    
            public ObservableCollection<Customer> Customers { get; private set; }
    
            private Customer _itemInEditMode = new Customer();
            public Customer ItemInEditMode
            {
                get { return _itemInEditMode;  }
            }
    

    <ComboBox ItemsSource="{Binding Customers}" SelectedItem="{Binding SelectedCustomer}" DisplayMemberPath="Name"/>
            <TextBox Text="{Binding ItemInEditMode.Name}"/>
    

    • Marked as answer by Alex Teslin Friday, July 5, 2013 12:58 PM
    Friday, July 5, 2013 11:12 AM
  • Add an individual customer to the view model. Bind TextBoxes to properties of the individual customer. Add a handler for CollectionViewSource.View.CurrentChanged. In the handler, do a deep copy from the CurrentItem to the individual customer.

    Bill Swartz

    • Marked as answer by Alex Teslin Thursday, July 11, 2013 6:21 PM
    Thursday, July 11, 2013 4:29 PM

All replies

  • I hope you know INotifyPropertyChanged interace and implemented for all properties in ViewModel.

    Bind your textbox's parent panel datacontext with comboxbox selected item with the help of elementname in binding.

     <ComboBox x:Name="cmbx" Width="150" ItemsSource="{Binding Path=FunctionEvents,Source=FunctionEvents, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" DisplayMemberPath="EventName"
                                          ></ComboBox>
            <StackPanel DataContext="{Binding ElementName=cmbx, Path=SelectedItem, Mode=TwoWay}">
                <TextBox Text="{Binding someproperty}"></TextBox>
                <TextBox Text="{Binding someotherproperty}"></TextBox>
            </StackPanel>

    As you bind an collection to a combobox, whenever user selects an item from dropdown, stackpanel datacontext changes and it will update all textboxes properties as per INotifyPropertyChanged

    let me know if you need more help.


    Thanks & Regards
    Syed Amjad Sr. Silverlight/WPF Developer,
    yahoo : syedamjad6736@yahoo.com, skype : syedamjad.0786.
    Please use Marked as Answer if my post solved your problem and use Vote As Helpful if a post was useful.

    Thursday, July 4, 2013 6:13 AM
  • Thanks Syed,

    I've tried your example but unfortunately I can't make it work, yet.

    Here is my xaml snippet:

    <UserControl x:Class="ProjectName.View.CustomerView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 >
        <StackPanel>
            <ComboBox 
                x:Name="cmbCustomers" 
                Width="200"
                ItemsSource="{Binding Path=ComboCustomers, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}"
                SelectedItem="{Binding Path=ComboSelectedItem}"
                DisplayMemberPath="col_name"
                >
            </ComboBox>
            <StackPanel DataContext="{Binding ElementName=cmbCustomers, Path=SelectedItem, Mode=TwoWay}">
                <TextBox Text="{Binding Path=Name}"></TextBox>
            </StackPanel>
        </StackPanel>
    </UserControl>


    These are my ViewModel Properties:

    public string Name
            {
                get { return _customer.col_name; }
                set
                {
                    if (value == _customer.col_name)
                        return;
                    _customer.col_name = value;
                    base.OnPropertyChanged("Name");
                }
            }
    public provider ComboSelectedItem
            {
                get
                {
                    return _provider;
                }
                set
                {
                    _customer = value;
                    base.OnPropertyChanged("ComboSelectedItem");
                    System.Windows.MessageBox.Show("Selected Item: " + _customer.col_name);
                }
            }
    public IList<customer> ComboCustomers
            {
                get 
                { 
                    return CustomerRepository.GetCustomers(); 
                }
            }

    As you can see in xaml "Source=ComboCustomers" is not there for Combo box.  If I included this the combo box wasn't showing anything.

    Also, in ComboSelectedItem property I can see the updated value/name in the message box. But for some reason the textboxes are blank. 

    If I first type in text in textbox, then select the item from the combobox, it will erase the text in the textbox, but not update.

    Any suggestions please ?

    Thursday, July 4, 2013 12:37 PM
  • i have a sample code for you, follow this and let me know.

    View

    <Window x:Class="WpfApplication2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:local="clr-namespace:WpfApplication2.ViewModel"
            Title="MainWindow" Height="350" Width="525" >
        <Window.Resources>
            <local:EmployeeViewModel x:Key="viewmodel">           
            </local:EmployeeViewModel>
        </Window.Resources>
        <Grid x:Name="LayoutRoot" DataContext="{StaticResource viewmodel}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition Height="50"></RowDefinition>
                <RowDefinition Height="200"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <TextBlock Text="Employee" Grid.Row="0" Grid.Column="0"></TextBlock>
            <ComboBox Grid.Row="0" Grid.Column="1"
                x:Name="cmbEmployees" 
                Width="200"
                ItemsSource="{Binding Path=Employees}"            
                DisplayMemberPath="Name"
                >
            </ComboBox>
            <Grid Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" DataContext="{Binding ElementName=cmbEmployees, Path=SelectedItem, Mode=TwoWay}">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBlock Text="Employee Id" Grid.Row="0" Grid.Column="0"></TextBlock>
                <TextBlock Text="{Binding Path=Id}" Grid.Row="0" Grid.Column="1"></TextBlock>
                <TextBlock Text="Employee Name" Grid.Row="1" Grid.Column="0"></TextBlock>
                <TextBlock Text="{Binding Path=Name}" Grid.Row="1" Grid.Column="1"></TextBlock>
                <TextBlock Text="Employee City" Grid.Row="2" Grid.Column="0"></TextBlock>
                <TextBlock Text="{Binding Path=City}" Grid.Row="2" Grid.Column="1"></TextBlock>
            </Grid>
        </Grid>
    </Window>
    

    ViewModel

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel;
    using WpfApplication2.Model;
    using System.Collections.ObjectModel;
    using System.Windows;
    
    namespace WpfApplication2.ViewModel
    {
        public class EmployeeViewModel : INotifyPropertyChanged
        {
            private ObservableCollection<Employee> _employees;
    
            public ObservableCollection<Employee> Employees
            {
                get
                {
                    return _employees;
                }
                set
                {
                    _employees = value;
                    FirePropertyChanged("Employees");
                }
            }
    
            public EmployeeViewModel()
            {
                Employees = new ObservableCollection<Employee>();
    
                for (var i = 0; i < 10; i++)
                {
                    Employees.Add(new Employee
                    {
                        City = "City"+i,
                        Id = i,
                        Name = "Name" + i
                    });
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void FirePropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }
    

    Model

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel;
    
    namespace WpfApplication2.Model
    {
        public class Employee : INotifyPropertyChanged
        {
            private int _id;
            public int Id
            {
                get {
                    return _id;
                }
                set
                {
                    _id = value;
                    FirePropertyChanged("Id");
                }
            }
    
            private string _name;
            public string Name
            {
                get
                {
                    return _name;
                }
                set
                {
                    _name = value;
                    FirePropertyChanged("Name");
                }
            }
    
            private string _city;
            public string City
            {
                get
                {
                    return _city;
                }
                set
                {
                    _city = value;
                    FirePropertyChanged("City");
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void FirePropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                   PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }
    


    Thanks & Regards
    Syed Amjad Sr. Silverlight/WPF Developer,
    yahoo : syedamjad6736@yahoo.com, skype : syedamjad.0786.
    Please use Marked as Answer if my post solved your problem and use Vote As Helpful if a post was useful.

    • Proposed as answer by talk2lal Sunday, December 25, 2016 6:59 AM
    Thursday, July 4, 2013 1:22 PM
  • No, still not work.  I have also changed the list of customers from IList to ObservableCollection, but that didn't help.

    It does work if I change the design of your example.  For example I removed the DataContext declaration from the Grid where Textboxes are.  I have to also call PropertyChange Event for each Property in my ViewModel.

    But I am not sure if this is the correct way of doing it as I have a limited understanding in MVVM and the fact that it doesn't work as your example.

    Thursday, July 4, 2013 3:31 PM
  • Hi alex,

    my previous post is the perfect way of implementation of MVVM and i will suggest you go ahead.

    Let me know if you have more doubts.


    Thanks & Regards
    Syed Amjad Sr. Silverlight/WPF Developer,
    yahoo : syedamjad6736@yahoo.com, skype : syedamjad.0786.
    Please use Marked as Answer if my post solved your problem and use Vote As Helpful if a post was useful.

    Thursday, July 4, 2013 3:54 PM
  • Hi,

    I have a View with combobox and some textboxes, which is responsible to add new Customer record.  When the View is displayed, the combobox displays of existing customers.  If user selects one from combobox I want the values displayed to textboxes.  User can choose to enter data manually without using combobox.

    My question is how can I update textboxes based on combobox selection in MVVM?  I can do this in Form's by manually updating the textboxes but in MVVM.

    I am not asking for the detailed solution, but the general solution would be much appreciated, like do I need to update relevant Properties in ViewModel? If so what is the best approach?

    Thanks 

    If your ComboBox displays Customers, your should bind the SelectedItem property to a property of type Customer of your view model:

    <ComboBox ItemsSource="{Binding Customers}" SelectedItem="{Binding SelectedCustomers}" DisplayMemberPath="Name"/>

    You then raise the PropertyChanged event in the setter of the property in the view model:

    private Customer _selectedCustomer;
            public Customer SelectedCustomer
            {
                get { return _selectedCustomer; }
                set { selectedCustomer = value; OnPropertyChanged("SelectedCustomer"); }
            }

    ..and bind the TextBox to a property of the SelectedCustomer object:

    <TextBlock Text="{Binding SelectedCustomer.Name}"/> 
    

    • Marked as answer by Alex Teslin Friday, July 5, 2013 8:24 AM
    Thursday, July 4, 2013 4:06 PM
  • But it didn't work.  For example if I use this:

    <StackPanel DataContext="{Binding ElementName=cmbCustomers, Path=SelectedItem, Mode=TwoWay}">
                <TextBox Text="{Binding Path=Name}"></TextBox>
            </StackPanel>

    it does not work.  But if I take out the StackPanel, then it works. 

    Also, in addition to taking out Textbox from a StackPanel, I have to raise PropertyChange Event for each property in ViewModel class.  If I don't do that my code never enters to Name property at run-time. Perhaps this might work without raising PropertyChange IF the Textbox can work inside the StackPanel with DataContext declaration.

     

    Thursday, July 4, 2013 4:13 PM
  • I think I've sent my last post before realising the Magnus's post.  I will try exactly that and will report of the outcome.

    Thanks guys

    Thursday, July 4, 2013 7:29 PM
  • Finally, Magnus's solution worked.  And it appears that I don't even need to bind DataContext for the parent control of the textboxes.

    Also, the Name property is updated implicitly, so that when I want to get the Name property value, it does return the correct value.  Seems to be working, although I haven't tested the solution in all eventualities, like passing the ViewModel object instance for saving it to database.

    Hope it will work all ok.

    Thank you Magnus and thanks to all for your help.

    Friday, July 5, 2013 8:23 AM
  • Oops, I found something not quite right.  When I select an Item from Combobox it updates/populates the Textbox.  But when I then try to amend a textbox (in case user needs to amend some textbox values that is) the Combobox is also updated.  The Combobox displays the name and that name is updates. 

    How can I stop that happening?  I've tried "Mode=Oneway" and "Mode=OneTime", but not helped.  If I can't stop this happening then I am in square one again.

    Friday, July 5, 2013 8:53 AM
  • Use another Customer property to bind the TextBoxes to if you don't want to change the property values of the one that is selected in the ComboBox:

            private Customer _selectedCustomer;
            public Customer SelectedCustomer
            {
                get { return _selectedCustomer; }
                set 
                { 
                    _selectedCustomer = value;
                    OnPropertyChanged("SelectedCustomer");
      //set properties of the object that is bound to the TextBoxes
                    _itemInEditMode.Name = _selectedCustomer.Name;
                    OnPropertyChanged("ItemInEditMode");
                }
            }
    
            public ObservableCollection<Customer> Customers { get; private set; }
    
            private Customer _itemInEditMode = new Customer();
            public Customer ItemInEditMode
            {
                get { return _itemInEditMode;  }
            }
    

    <ComboBox ItemsSource="{Binding Customers}" SelectedItem="{Binding SelectedCustomer}" DisplayMemberPath="Name"/>
            <TextBox Text="{Binding ItemInEditMode.Name}"/>
    

    • Marked as answer by Alex Teslin Friday, July 5, 2013 12:58 PM
    Friday, July 5, 2013 11:12 AM
  • Oh, I see.  I will try that now.  This suggestion then perhaps can answer my other question on saving the Customer object (which I've created as a new thread here).  My question there is if selected Customer Item copied to CustomerViewModel class's _customer, then saving that Customer instance would save everything from the selected Item.

    So perhaps having two instances, now I can use the second, _itemInSelectedMode instance to pass it to save to database.

    Anyway I haven't done this before so it's just my guess - I still need to search for examples of saving it to database.

    Thanks for your suggestion 

    Friday, July 5, 2013 12:14 PM
  • It seems that it's working fine.  I will now move to validation and DataErrorInfo etc. And then finally saving it to database.

    Thank you Magnus

    Friday, July 5, 2013 12:58 PM
  • I think I might need to go back to the original implementation - on ComboSelected update all ViewModel properties by raising OnPropertyChanged event for each column/property name.

    Otherwise I can't see how can I implement IDataErrorInfo.  I wasn't aware until now that the interface implementation uses class properties. And I need to raise errors in ViewModel class. Unless there is another solution for this which I am still not aware of.

    Sunday, July 7, 2013 8:59 PM
  • Does your Customer class implement both INotifyPropertyChanged and IDataErrorInfo? Is the Mode set to TwoWay for the Bindings in the TextBoxes in the details area of your Window? What is the value of property UpdateSourceTrigger for these Bindings?

    For collections in the view model that are bound to ComboBoxes and the like, I use ListCollectionViews. This allows me to access the SelectedItem of the ComboBox in the view model as the CurrentItem of the ListCollectionView.


    Bill Swartz

    Sunday, July 7, 2013 9:42 PM
  • Thanks Bill,

    I use combo box to let user select an item (which is the record from existing table), and populate all the textboxes based on the value selected from the combo box.  Also, user can edit any of the textboxes if needs to.  Additional constraint is that when user types in the textbox, it should not update the combo box.  So I've created two class instances, one for combo box and another for textboxes, as suggested by Magnus. 

    In order to do the above I've added ComboSelectedItem property to ViewModel class which copies from the item/object selected in combo box to another object/instance (which is used by textboxes.

    So the textboxes are all bound to ComboSelectedItem property rather than their individual properties.  Hence when user changes them their properties not Set.  However it does get the right value because the copying happens in ComboSelectedItem to another instance.

    In order to update properly all the properties, I need to raise them from ComboSelectedItem.  Otherwise how can I populate textboxes based on combo box selection ?

    Monday, July 8, 2013 9:01 AM
  • So the textboxes are all bound to ComboSelectedItem property rather than their individual properties.  Hence when user changes them their properties not Set.  However it does get the right value because the copying happens in ComboSelectedItem to another instance.


    I don't quite understand. The texboxes should bind to the properties of a Customer object in the viewmodel. This means that the setter of the bound property will be called whenever you change a value in a textbox provided that the binding's Mode is set to TwoWay which is the default for the Text property of a TextBox. Would please post some minimal code sample that demonstrates your current issue?
    Monday, July 8, 2013 12:36 PM
  • I also don't see how you distinguish between adding a new customer and editing the currently selected customer. If I were doing it, I would have an individual customer in the view model in addition to the collection of customers. When adding, the individual customer would reference a new customer object. When editing, the individual customer would reference the currently selected customer in the list.

    Bill Swartz

    Monday, July 8, 2013 2:10 PM
  • I tried to copy only the minimum relevant places:

    Part of CustomerViewModel

    public IList<Customer> ComboCustomers
            {
                get
                {
                    return CustomerRepository.GetCustomers();
                }
                set
                {
                    _customers = value;
                    base.OnPropertyChanged("ComboProviders");
                }
            }
    public string Name
            {
                get { return _customer.c_name; }
                set
                {
                    if (value == _customer.c_name)
                        return;
                    _customer.c_name = value;
                    base.OnPropertyChanged("Name");
                }
            }
            public string Email
            {
                get { return _customer.c_email; }
                set
                {
                    if (value == _customer.c_email)
                        return;
                    _customer.c_email = value;
                    base.OnPropertyChanged("Email");
                }
            }
            public string Website
            {
                get { return _customer.c_website; }
                set
                {
                    if (value == _customer.c_website)
                        return;
                    _customer.c_website = value;
                    base.OnPropertyChanged("Website");
                }
            }
    public provider ComboSelectedItem
            {
                get { return _selectedCustomer; }
                set
                {
                    _selectedCustomer = value;
                    base.OnPropertyChanged("ComboSelectedItem");
                    //Set properties of the object bound to TextBoxes
                    _customer.c_name = _selectedCustomer.c_name;
                    _customer.c_email = _selectedCustomer.c_email;
                    _customer.c_website = _selectedCustomer.c_website;
                    //Update ViewModel properties
                    base.OnPropertyChanged("Name");
                    base.OnPropertyChanged("Email");
                    base.OnPropertyChanged("Website");
                }
            }

    Part of CustomerView:

    <UserControl x:Class="project_name.View.CustomerView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vw="clr-namespace.project_name.View" MinWidth="300" MinHeight="300"> <UserControl.Resources> <!-- This style ensures that the borders in the main window are consistent. --> <Style x:Key="ViewBorderStyle" TargetType="{x:Type Border}"> <Setter Property="Background" Value="WhiteSmoke" /> <Setter Property="BorderBrush" Value="DarkGray" /> <Setter Property="BorderThickness" Value="2" /> <Setter Property="CornerRadius" Value="5" /> <Setter Property="SnapsToDevicePixels" Value="True" /> </Style> </UserControl.Resources> <DockPanel> <!--Selection boxes--> <Border DockPanel.Dock="Top" Style="{StaticResource ViewBorderStyle}"> <StackPanel Orientation="Horizontal"> <!--Combobox of List of Customers--> <Label Content="Customers:" HorizontalAlignment="Right" Target="{Binding ElementName=cmbCustomers}" /> <ComboBox x:Name="cmbCustomers" Width="200" ItemsSource="{Binding Path=ComboCustomers}" Validation.ErrorTemplate="{x:Null}" SelectedItem="{Binding Path=ComboSelectedItem}" > <ComboBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding c_URN, UpdateSourceTrigger=LostFocus}" /> <TextBlock Text="{Binding c_name}" Padding="10,0,0,0" /> </StackPanel> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> </StackPanel> </Border> <Border DockPanel.Dock="Top" HorizontalAlignment="Stretch" Background="White" Height="3"/> <Border DockPanel.Dock="Top" Style="{StaticResource ViewBorderStyle}"> <!--Input boxes, text boxes etc --> <Grid Margin="4"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="6"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="30"/> <RowDefinition Height="Auto"/> <RowDefinition Height="30"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.Resources> <DataTemplate DataType="{x:Type ValidationError}"> <TextBlock FontStyle="Italic" Foreground="Red" HorizontalAlignment="Right" Margin="0,1" Text="{Binding Path=ErrorContent}" /> </DataTemplate> </Grid.Resources> <!--Name--> <Label Grid.Row="0" Grid.Column="0" Content="Name:" HorizontalAlignment="Right" Target="{Binding ElementName=txtName}" /> <TextBox x:Name="txtName" Grid.Row="0" Grid.Column="2" Text="{Binding Name, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" Validation.ErrorTemplate="{x:Null}" /> <ContentPresenter Grid.Row="1" Grid.Column="2" Content="{Binding ElementName=txtName, Path=(Validation.Errors).CurrentItem}" /> <!--Email Address--> <Label Grid.Row="2" Grid.Column="0" Content="Email:" HorizontalAlignment="Right" Target="{Binding ElementName=txtEmail}" /> <TextBox x:Name="txtEmail" Grid.Row="2" Grid.Column="2" Text="{Binding Email, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" Validation.ErrorTemplate="{x:Null}" /> <ContentPresenter Grid.Row="3" Grid.Column="2" Content="{Binding ElementName=txtEmail, Path=(Validation.Errors).CurrentItem}" /> <!--Website Address--> <Label Grid.Row="4" Grid.Column="0" Content="Website:" HorizontalAlignment="Right" Target="{Binding ElementName=txtWebstie}" /> <TextBox x:Name="txtWebsite" Grid.Row="4" Grid.Column="2" Text="{Binding Website, ValidatesOnDataErrors=False, UpdateSourceTrigger=PropertyChanged}" Validation.ErrorTemplate="{x:Null}" /> <ContentPresenter Grid.Row="5" Grid.Column="2" Content="{Binding ElementName=txtWebsite, Path=(Validation.Errors).CurrentItem}" /> <!-- SAVE BUTTON --> <Button Grid.Row="6" Grid.Column="2" Command="{Binding Path=SaveCommand}" Content="_Save" HorizontalAlignment="Right" Margin="4,2" MinWidth="60" /> </Grid> </Border> </DockPanel> </UserControl>

    I think there is a confusion about editing and creating customers.  There is no editing of existing customers at all.  This view is solely to create new customer.  The combo box there is only to enable user to base new customer on an existing one.  Say out of 50 properties that existising customer has, and only 2 properties will differ from the new customer that user tries to add, then to save time user should be able to select from that existing customer (from combo box), then view should populate all the textboxes with the values based on that existing customer. User then can go and manually change those 2 properties/textboxes and then go ahead to add/save todatabase. 

    It's really straightforward scenario that I've been doing for while in Access Forms.  But WPF is completely new to me.

    Tuesday, July 9, 2013 2:30 PM
  • If I read your code correctly, you are not binding your combobox to an observablecollection. Try wrapping your customers list in an observablecollection, and then bind the combobox to the observablecollection.

    Bill Swartz

    Wednesday, July 10, 2013 2:03 PM
  • I did that already by it didn't help.  I thought the ObservableCollection allows to sync between the target and source.  My ComboSelectedItem updates Customer object within the List.  Regardless if I used ObservableCollection or not the ComboSelectedItem does not sets any properties.  So that is why I had to call each Property from ComboSelectedItem.

    Wednesday, July 10, 2013 2:16 PM
  • Are you adding the new customer to the list or to the observablecollection?

    Bill Swartz

    Wednesday, July 10, 2013 4:47 PM
  • That is the separate issue here.  I am at the moment concerned only with user interaction. Namely, the implementation of Combobox and Textboxes where Combobox selection updates all other textboxes with the selected item.

    Thursday, July 11, 2013 8:12 AM
  • In that case, create a CollectionViewSource in the view model. Set its Source property to an ObservableCollection of customers. Bind the ItemsSource property of the ComboBox to the View property of the CollectionViewSource. Bind the Text properties of the TextBoxes to properties of View.CurrentItem

    Bill Swartz

    Thursday, July 11, 2013 2:45 PM
  • Yes, that's how I've got implemented now.  But this also means public ViewModel properties are not updated and hence Validation with IDataErrorInfo will not work.

    But I suppose there is no other way, either one or the other.

    Thursday, July 11, 2013 3:27 PM
  • Add an individual customer to the view model. Bind TextBoxes to properties of the individual customer. Add a handler for CollectionViewSource.View.CurrentChanged. In the handler, do a deep copy from the CurrentItem to the individual customer.

    Bill Swartz

    • Marked as answer by Alex Teslin Thursday, July 11, 2013 6:21 PM
    Thursday, July 11, 2013 4:29 PM
  • Add a handler for CollectionViewSource.View.CurrentChanged.  I think this an area where I am not quite comfortable yet.  I think I need to study on Handlers, delegates and event raises.  I can't see otherwise been able to continue working in WPF.

    Thanks Bill

    Thursday, July 11, 2013 6:21 PM
  • Thanks! You saved me Hours :)
    Sunday, December 25, 2016 6:58 AM