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

Column IsVisible does not bind with late DataContext binding

2 Answers 516 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Louis
Top achievements
Rank 1
Louis asked on 15 May 2014, 03:56 PM
I've run into a problem where if the DataContext is set too late in the initialization/rendering process, bindings on the IsVisible property of columns are never established. Below is an example showing the problem.

If you establish the DataContext in the constructor, it works as expected; the Number column is not shown, and you can toggle its display using the checkbox.

However, if you comment out that line, run the app, and use the button to establish the DataContext after the grid has rendered, the Number column is shown even though ShowNumber is false, and the binding does not respond to changes in ShowNumber (again using the checkbox).

I found a work-around by re-establishing the binding after setting the DataContext, but this is ugly and much less maintainable.

Is there a way I can force it to update the column bindings when the DataContext is set, rather than re-creating the binding for every column on which I need to control visibility?

Thanks,
Louis

XAML:
<Window x:Class="DelayedBinding.MainWindow"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <telerik:RadGridView Grid.Row="0" x:Name="radGridView" AutoGenerateColumns="False" ItemsSource="{Binding Path=Items}"
                                 IsFilteringAllowed="False" ShowGroupPanel="False" CanUserSortColumns="False">
            <telerik:RadGridView.Columns>
                <telerik:GridViewDataColumn Header="Name" Width="65"
                                            DataMemberBinding="{Binding Path=Name}"/>
                <telerik:GridViewDataColumn IsVisible="{Binding Path=ShowNumber}" Header="Number" Width="65" x:Name="NumberColumn"
                                            DataMemberBinding="{Binding Path=Number}"/>
                <telerik:GridViewDataColumn Header="Group" Width="65"
                                            DataMemberBinding="{Binding Path=Group}"/>
            </telerik:RadGridView.Columns>
        </telerik:RadGridView>
        <StackPanel Grid.Row="1" Orientation="Horizontal">
            <Button Click="ConnectVM" Content="ConnectVM" Margin="5"/>
            <CheckBox IsChecked="{Binding Path=ShowNumber}" Content="Show Number" VerticalAlignment="Center"/>
        </StackPanel>
    </Grid>
</Window>

Code-behind:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
 
namespace DelayedBinding
{
    public class Item
    {
        public string Name { get; set; }
        public int Number { get; set; }
        public string Group { get; set; }
    }
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public ObservableCollection<Item> Items { get; private set; }
        private bool _ShowNumber = false;
 
        public bool ShowNumber
        {
            get { return _ShowNumber; }
            set
            {
                _ShowNumber = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("ShowNumber"));
            }
        }
 
        public MainWindow()
        {
            Items = new ObservableCollection<Item>();
            for (int i = 0; i < 5; i++)
                Items.Add(new Item() { Name = "Object " + i, Number = i, Group = (i % 2 == 1 ? "Odd" : "Even") });
            InitializeComponent();
            // If we connect the DataContext here, everything works fine!
            DataContext = this;
        }
 
        private void ConnectVM(object sender, RoutedEventArgs e)
        {
            // If we wait to connect it here, the ShowNumber binding isn't established!
            DataContext = this;
            // This is the work-around, by re-establishing the binding, the grid again works correctly.
            //NumberColumn.SetBinding(Telerik.Windows.Controls.GridViewColumn.IsVisibleProperty, "ShowNumber");
        }
    }
}

2 Answers, 1 is accepted

Sort by
0
Louis
Top achievements
Rank 1
answered on 15 May 2014, 03:58 PM
Very sorry, I just realized I posted this to the wrong forum. This is about RadGridView, not RadChartView. Could it be moved to the appropriate forum? I don't see any way for me to remove or move it myself.

Thanks,
Louis
0
Boris
Telerik team
answered on 20 May 2014, 08:26 AM
Hello Louis,

We tested your application and there really is an issue. When we debugged the solution, we found that the DataContext gets updated, but when we tried to force update on the binding target, an error that DataContext is null occurs, which is clearly an issue with the WPF data binding mechanism. A possible cause for this behavior might be that columns of the GridView are not actually in the visual tree. 

As an alternative to this, you can either use your workaround, or set an explicit Source to the binding, so that it does not depend on the DataContext of the column.

Regards,
Boris Penev
Telerik
 
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
 
Tags
GridView
Asked by
Louis
Top achievements
Rank 1
Answers by
Louis
Top achievements
Rank 1
Boris
Telerik team
Share this question
or