1

I can't seem to get my visibilty converter to work. I think the issue is that i'm setting the relevant property in the constructor, so it's not picking it up down the line. Code is below, any suggestions as to how I can fix this?

MainWindowViewModel: (this is the main page; clicking a button will open a second window)

var newWindow = new SecondaryWindow
                {
                    Title = title,
                    DataContext = new SecondaryWindowViewModel{MyData = data, ShowAdditionalColumns = false}
                };
newWindow.Show();

Secondary Window: Here's the relevant XAML:

    <Window.Resources>
        <myApp:DataGridVisibilityConverter x:Key="gridVisibilityConverter" />
    </Window.Resources>

<DataGrid ItemsSource="{Binding Path=MyData}" AutoGenerateColumns="False" >
                <DataGrid.Columns>
                    <DataGridCheckBoxColumn Header="Print" Binding="{Binding Path=IsSelected}"/>
                    <DataGridTextColumn Header="FirstName" Binding="{Binding Path=FirstName}" IsReadOnly="True"/>
                    <DataGridTextColumn Header="LastName" Binding="{Binding Path=LastName}" IsReadOnly="True"/>
                    <DataGridTextColumn Header="Lines" Binding="{Binding Path=TotalLines}" IsReadOnly="True" Visibility="{Binding Path=ShowAdditionalColumns, Converter={StaticResource gridVisibilityConverter}}"/>

And the Secondary ViewModel code:

private bool showAdditionalColumns;
public bool ShowAdditionalColumns
{
    get { return showAdditionalColumns; }
    set
    {
        showAdditionalColumns= value;
        NotifyPropertyChanged(() => ShowAdditionalColumns);
    }
}

Here's the converter; pretty standard stuff here. I've put a breakpoint in the convert method; and it's never hit:

[ValueConversion(typeof(bool), typeof(Visibility))]
public class DataGridVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var booleanValue = (bool)value;
        return booleanValue ? Visibility.Visible : Visibility.Hidden;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
Jim B
  • 8,344
  • 10
  • 49
  • 77
  • Please show code for the visibility converter. – Will Custode Feb 12 '14 at 13:28
  • Since the object isn't fully constructed when the property is set nothing can be listening for the property changed event. Some crazy ideas: Is there a reason that ShowAdditionalColumns can't be a Dependency property? I believe that would solve the problem. Or you could setup a handler for the SecondaryWindow's DataContextChanged event and set the property in the handler... –  Feb 12 '14 at 13:42
  • Does the output window complain anything? Other `DataGridTextColumn`s bind correctly? – Mat J Feb 12 '14 at 13:42
  • `NotifyPropertyChanged(() => ShowAdditionalColumns);` What it does.. Show the `PropertyChanged` implementation.. – Sankarann Feb 12 '14 at 13:52

1 Answers1

0

The DataGrid's columns are not part of the visual/logical tree, so they don't get the DataContext inheritance. If you debug the program, you'll see the error in the output window:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element.

There are a few options here.

  • Use this solution: http://blogs.msdn.com/b/jaimer/archive/2008/11/22/forwarding-the-datagrid-s-datacontext-to-its-columns.aspx
  • Reference some control that does have an appropriate data context. It's easiest to use the root container (e.g. user control).

    First initialize a resource named "This" in code (must be called before InitializeComponent):

    public MyUserControl()
    {
        Resources["This"] = this;
        InitializeComponent();
    }
    

    Then reference it in XAML:

    <DataGridTextColumn Visibility="{Binding Source={StaticResource This},
                        Path=DataContext.ShowAdditionalColumns,
                        Converter={StaticResource gridVisibilityConverter}}" />
    

(As a side note, the binding you provide for the column's data works because it is copied to the row in the grid, where the data context is set by the DataGrid to the data item.)

Eli Arbel
  • 22,391
  • 3
  • 45
  • 71