views:

25

answers:

3

Hi, I have a datagrid in which I would like to show the details when a row is clicked, and hide it when the user clicks again.

DataGridRowDetailsVisibilityMode.VisibleWhenSelected

only allows to show one details row at a time. The other options seem to be All or Nothing.

What is the workaround?

Thanks!

A: 

May be it is possible to set DataGridRowDetailsVisibilityMode to Visible, and change row details template to be hidden or expanded depends of condition your need.

STO
A: 

You could manage the state yourself.

Have the visibility of the detail bound to property on the underlying object and simply toggle the value of this property when the row is selected or deselected.

James
the value to bing against would be more something that would memorize whether the row has been clicked an odd number of time, isn't it?
bmanu
Or a Boolean that gets toggled each time it is clicked (flag = !flag). Same thing.
James
Could you please post some code, I'm new to Xaml! Thanks!
bmanu
A: 

OK. Based on the request for code...

Here is the XAML for a hypothetical grid:

        <data:DataGrid x:Name="TheGrid" AutoGenerateColumns="False">
        <data:DataGrid.Columns>
            <data:DataGridTemplateColumn Header="Items">
                <data:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Grid MouseLeftButtonDown="Item_MouseLeftButtonDown">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Grid.Column="0" Text="{Binding Title}" Margin="5"/>
                            <TextBlock Grid.Column="1" Text="{Binding Desc}" Visibility="{Binding DescVisibility}"  Margin="5"/>
                        </Grid>
                    </DataTemplate>
                </data:DataGridTemplateColumn.CellTemplate>
            </data:DataGridTemplateColumn>
        </data:DataGrid.Columns>
    </data:DataGrid>

Note the use of a DataTemplate for the column and the inclusion of two text items. The second TextBlock has its visibility bound to DescVisibility. Also note the click event on the grid.

Here is the code for the data object that we are binding to each row:

        public class AnItem : INotifyPropertyChanged
    {
        public AnItem(string title, string desc)
        {
            Title = title;
            Desc = desc;
        }

        public string Title { get; set; }
        public string Desc { get; set; }


        private bool _toggleState { get; set; }
        public bool ItemToggled
        {
            get { return _toggleState; }
            set
            {
                if (_toggleState != value)
                {
                    _toggleState = value;
                    OnPropertyChanged("ItemToggled");
                    OnPropertyChanged("DescVisibility");
                }
            }
        }

        public Visibility DescVisibility
        {
            get
            {
                if (_toggleState)
                    return Visibility.Visible;
                else
                    return Visibility.Collapsed;
            }
        }

        #region INotifyPropertyChanged implementation

        /// <summary>
        /// This event is fired when any of the property values change on this object
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Raises the PropertyChanged event for the passed in property
        /// </summary>
        protected void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion INotifyPropertyChanged Implementation
    }

This object implements INotifyPropertyChanged so that it plays nice with binding and it has two special properties. A read/write boolean for maintaining state and a read only visibility value which simply saves us from using a boolean/visibility converter in the binding because I'm lazy.

The final piece is the event handler for the click event which is pretty simple:

        private void Item_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (((Grid)sender).DataContext is AnItem)
        {
            AnItem item = ((Grid)sender).DataContext as AnItem;
            item.ItemToggled = !item.ItemToggled;
        }
    }

Finally, for completeness only, here is the code to set the item source for the grid:

        public List<AnItem> TheItems = new List<AnItem>();

    public MainPage()
    {
        InitializeComponent();

        TheItems.Add(new AnItem("Title1", "The description for the first item"));
        TheItems.Add(new AnItem("Title2", "The description for the second item"));
        TheItems.Add(new AnItem("Title3", "Maybe I should be more imaginative with descriptions"));
        TheGrid.ItemsSource = TheItems;
    }

Hope this helps.

James