This is a migrated thread and some comments may be shown as answers.

Items in ComboBoxColumn don't get updated when DataContext changes

5 Answers 123 Views
GridView
This is a migrated thread and some comments may be shown as answers.
ClausDC
Top achievements
Rank 1
Iron
Iron
Iron
ClausDC asked on 18 Mar 2011, 09:26 AM
Hi,

as the thread titles says, if I change the DataContext of a GridView, a ComboBoxColumn whose ItemsSource binds to a collection in the DataContext don't change with changing the DataContext. Instead the values of the DataContext which was assigned before remain.

If I check

this.GridView.Columns[4].GetBindingExpression(GridViewComboBoxColumn.ItemsSourceProperty).DataItem


while debugging, I can see that "DataItem" still references the old DataContext -although-

this.GridView.Columns[4].DataContext


references the newly assigned DataContext.

I do not understand this behavior. Thanks.

5 Answers, 1 is accepted

Sort by
0
Maya
Telerik team
answered on 18 Mar 2011, 09:30 AM
Hello Claus,

May you provide a bit more details about your exact requirement and the main purpose of changing the DataContext  ? Furthermore, how exactly do you change it ?
 

Best wishes,
Maya
the Telerik team
0
ClausDC
Top achievements
Rank 1
Iron
Iron
Iron
answered on 18 Mar 2011, 09:47 AM
I have a UserControl which represents the View.

This View contains a GridView.

I change the DataContext by simply assigning the property "DataContext" of the View a new DataContext (ViewModel).

The purpose of changing the DataContext of the View is to display different values in the View - and by that in the GridView as well.

The setup I have is relatively complex but I think that this issue can be narrowd down to these simple steps.
0
Maya
Telerik team
answered on 21 Mar 2011, 03:47 PM
Hello Claus,

May you take a look at the sample project attached and let me know whether there is some misunderstandings on your requirements ? 

Best wishes,
Maya
the Telerik team
0
ClausDC
Top achievements
Rank 1
Iron
Iron
Iron
answered on 25 Mar 2011, 10:55 AM
Hi Maya,

thanks for your sample project.

It encapsulates what I'm doing very well but unfortunately you kind of "cheat" by setting the ItemsSource of the GridViewComboBoxColumn "by hand" i. e. you assign it directly

((GridViewComboBoxColumn)this.playersGrid.Columns[4]).ItemsSource = model2.Clubs;      


while I use binding to set the ItemsSource.

Assigning it directly when the DataContext changes works perfectly fine, unfortunately this is not an option for me and binding should work, shouldn't it?

I have modified your sample project so that it resembles my setup and shows the issue:

MyViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;
  
namespace GridViewComboBoxColumn_WPF
{
    public class MyViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
  
          
        private ObservableCollection<Player> players;
        private object selectedItem;
  
        private ObservableCollection<Club> _Clubs;
  
  
        public ObservableCollection<Club> Clubs
        {
            get
            {
                return _Clubs;
            }
            set
            {
                _Clubs = value; OnPropertyChanged("Clubs");
            }
        }
  
        public ObservableCollection<Player> Players
        {
            get
            {
                if (this.players == null)
                {
                    this.players = Player.GetPlayers();
                }
  
                return this.players;
            }
        }
  
        public object SelectedItem
        {
            get { return this.selectedItem; }
            set
            {
                if (value != this.selectedItem)
                {
                    this.selectedItem = value;
                    this.OnPropertyChanged("SelectedItem");
                }
            }
        }
  
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, args);
            }
        }
  
        private void OnPropertyChanged(string propertyName)
        {
            this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
  
        public MyViewModel()
        {
            this.Clubs = Club.GetClubs();
        }
    }
}

MyViewModel2:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;
  
namespace GridViewComboBoxColumn_WPF
{
    class MyViewModel2 : INotifyPropertyChanged
    {
        private ObservableCollection<Club> clubs;
        private ObservableCollection<Player> players;
        private object selectedItem;
  
        public event PropertyChangedEventHandler PropertyChanged;
        private ObservableCollection<Club> _Clubs;
  
  
        public ObservableCollection<Club> Clubs
        {
            get
            {
                return _Clubs;
            }
            set
            {
                _Clubs = value; OnPropertyChanged("Clubs");
            }
        }
  
        public ObservableCollection<Player> Players
        {
            get
            {
                if (this.players == null)
                {
                    this.players = Player.GetPlayers();
                }
  
                return this.players;
            }
        }
          
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, args);
            }
        }
  
        private void OnPropertyChanged(string propertyName)
        {
            this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
  
        public MyViewModel2()
        {
            this.Clubs = Club.GetClubs2();
        }
    }
}

MainWindow.xaml.cs:
using System.Windows;
using Telerik.Windows.Controls;
  
namespace GridViewComboBoxColumn_WPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
  
            MyViewModel vm = new MyViewModel();
  
            this.DataContext = vm;
            this.playersGrid.DataContext = vm;
            //((GridViewComboBoxColumn)this.playersGrid.Columns[4]).ItemsSource = Club.GetClubs();
              
        }
  
        private void RadButton_Click(object sender, RoutedEventArgs e)
        {
            this.playersGrid.Rebind();
            MyViewModel2 model2 = new MyViewModel2();
            this.DataContext = model2;
            this.playersGrid.DataContext = model2;
            this.playersGrid.ItemsSource = model2.Players;
            //((GridViewComboBoxColumn)this.playersGrid.Columns[4]).ItemsSource = model2.Clubs;         
        }
    }
}

MainWindow.xaml:
<Window x:Class="GridViewComboBoxColumn_WPF.MainWindow"
        xmlns:my="clr-namespace:GridViewComboBoxColumn_WPF"
        Title="MainWindow" Height="700" Width="700">
    <Window.Resources>
        <my:MyViewModel x:Key="MyViewModel"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <telerik:RadGridView Name="playersGrid" 
                             ItemsSource="{Binding Players}" 
                             AutoGenerateColumns="False">
            <telerik:RadGridView.Columns>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Name}"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Number}"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Position}"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Country}"/>
                <telerik:GridViewComboBoxColumn 
                    ItemsSource="{Binding Path=Clubs, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                    DataMemberBinding="{Binding ClubID}" 
                                                SortMemberPath="SortID"
                                                SelectedValueMemberPath="ID" 
                                                DisplayMemberPath="Name" 
                    >
                      
  
  
                </telerik:GridViewComboBoxColumn>
            </telerik:RadGridView.Columns>
        </telerik:RadGridView>
          
        <telerik:RadButton Content="Change DataContext" Click="RadButton_Click" Grid.Row="1" />
    </Grid>
</Window>

Thanks!
0
Pavel Pavlov
Telerik team
answered on 30 Mar 2011, 02:49 PM
Hello ClausDC,

Unfortunately the binding would not work . You will need to set the ItemsSource.
The reason is that  internally things work the following way: ItemsSource setting is being taken from the combo column and cloned for the lookup elements inside cells.

Cells have different context from the parent gird - the business object relevant to the row -  thus they will not sense any changes in the context of the parent grid.

So the workaround would be either to set the ItemsSource or in case you need the binding - expose your model as a static resource  and use binding to a static resource.

Best wishes,
Pavel Pavlov
the Telerik team
Tags
GridView
Asked by
ClausDC
Top achievements
Rank 1
Iron
Iron
Iron
Answers by
Maya
Telerik team
ClausDC
Top achievements
Rank 1
Iron
Iron
Iron
Pavel Pavlov
Telerik team
Share this question
or