4

I have dates bounded to TreeView. There is a wrapper class for date. Dates groups by years and months. Wrapper class also has IsSelected and IsExpanded properties:

public sealed class DateViewModel : NotificationObject, IEditableObject
{
    #region properties

    bool _isSelected;

    public bool IsSelected
    {
        get
        {
            return _isSelected;
        }
        set
        {
            if (_isSelected != value)
            {
                _isSelected = value;
                RaisePropertyChanged(() => IsSelected);
            }
        }
    }


    bool _isExpanded;

    public bool IsExpanded
    {
        get
        {
            return _isExpanded;
        }
        set
        {
            if (_isExpanded != value)
            {
                _isExpanded = value;
                RaisePropertyChanged(() => IsExpanded);
            }
        }
    }

    DateTime _date;

    public DateTime Date
    {
        get
        {
            return _date;
        }
        set
        {
            if (_date != value)
            {
                _date = value;

                RaisePropertyChanged(() => Date);
                RaisePropertyChanged(() => Year);
                RaisePropertyChanged(() => Month);
                RaisePropertyChanged(() => MonthName);
                RaisePropertyChanged(() => Day);
            }
        }
    }

    public int Year
    {
        get
        {
            return Date.Year;
        }
    }

    public int Month
    {
        get
        {
            return Date.Month;
        }
    }

    public string MonthName
    {
        get
        {
            return CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(Date.Month);
        }
    }

    public int Day
    {
        get
        {
            return Date.Day;
        }
    }

    #endregion properties
}

ObservableCollection of DateViewModel is used as ItemsSource for TreeView. Dates groups by CollectionViewSource ans DataTemplates:

<DataTemplate x:Key="DayTemplate">
    <TextBlock x:Name="textBlock"
               FontSize="14"
               Text="{Binding Path=Day}" />
</DataTemplate>

<HierarchicalDataTemplate x:Key="MonthTemplate"
                          ItemsSource="{Binding Path=Items}"
                          ItemTemplate="{StaticResource DayTemplate}">
    <TextBlock Text="{Binding Path=Name}" />
</HierarchicalDataTemplate>

<HierarchicalDataTemplate x:Key="YearTemplate"
                          ItemsSource="{Binding Path=Items}"
                          ItemTemplate="{StaticResource MonthTemplate}">
    <TextBlock>
        <Run Text="{Binding Path=Name, Mode=OneWay}" />
        <Run Text="y" />
    </TextBlock>
</HierarchicalDataTemplate>

<telerik:RadTreeView   Grid.Row="1"
          ItemsSource="{Binding Path=Dates.View.Groups}"
          ItemTemplate="{StaticResource YearTemplate}">           
    <telerik:RadTreeView.ItemContainerStyle>
        <Style TargetType="{x:Type telerik:RadTreeViewItem}">
            <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
            <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
        </Style>
    </telerik:RadTreeView.ItemContainerStyle>
</telerik:RadTreeView>

The issue is: I need to expand full path to date using view model by setting IsExpanded property to true. But it doesn't have effect.

UPDATE:

Yes I created group descriptions in code. The code for expanding is simple:

public sealed class DatesViewModel
{
    ObservableCollection<DateViewModel> _dates = new ObservableCollection<DateViewModel>();
    public CollectionViewSource Dates {get; set;}

    public DatesViewModel()
    {
        Dates = new CollectionViewSource { Source = _dates } ;

        // add groups, sorts and fill collection
        ...
    }

    // Just a sample
    public void ExpandFirstDate()
    {
        _dates[0].IsExpanded = true;
    }
}

There is missing code above.

Also I prepared test sample TreeViewGroupingSample.7z

Y.Yanavichus
  • 2,387
  • 1
  • 21
  • 34
  • Welcome back John! What is happening actually? Does not expand at all? – WPF-it Sep 27 '11 at 11:20
  • @AngelWPF: Hi! In short words: how to expand whole path to current selected item. CollectionViewGroupInternal doesn't have the IsExpanded property. – Y.Yanavichus Sep 27 '11 at 11:27
  • Have you added `GroupDescriptions` this way? `Dates.View.GroupDescriptions.Add(new GroupDescription("Year")); Dates.View.GroupDescriptions.Add(new GroupDescription("Month")); Dates.View.GroupDescriptions.Add(new GroupDescription("Day"));` – WPF-it Sep 27 '11 at 11:51
  • Can you post the code you are using to expand the TreeView from the ViewModel? Also, do you know if this works with a regular TreeView instead of the Telerik one? I know Telerik controls have some bugs that can cause unexpected behavior – Rachel Sep 27 '11 at 12:20

1 Answers1

2

Your TreeView is binding to CollectionViewSource.View.Groups, and those PropertyGroupDescription objects do not contain IsSelected or IsExpanded properties, so your TreeViewItem.IsSelected and TreeViewItem.IsExpanded values have an invalid binding

Your DatesViewModel.IsExpanded IS getting set to true with the code you are using. You can verify this by changing your Day template to show the value of IsExpanded

I would recommend creating classes for each tier (Year, Month, and Day), and having them all inherit from something like a TreeNodeBase class which contains properties for IsSelected, IsExpanded, and ObservableCollection<TreeNodeBase> Children. Don't forget to hook up a PropertyChange notification for your Children so that when TreeNodeBase.IsExpanded gets changed, the parent object's IsExpanded value changes too

Rachel
  • 130,264
  • 66
  • 304
  • 490
  • I also thought about base class but wanted to keep all so simple as possible. – Y.Yanavichus Sep 27 '11 at 16:38
  • Well if you want two-way binding on `IsSelected` and `IsExpanded`, you need objects to hold those values for each tier (year, month, and day). I would find it much simpler to create a base class for those 3 objects than to create 3 separate objects and have to code everything 3x – Rachel Sep 27 '11 at 16:40
  • I meant such solution, not only base class :) Recently I began to notice that I write too much code and don't use standard WPF futures. – Y.Yanavichus Sep 27 '11 at 16:47
  • One of the key things to remember with WPF's TreeView is it is simply a pretty-looking UI layer that is used to display your data. This is unlike WinForm's TreeView where the TreeView is an actual object with it's own properties and data. If you want a hierarchy of data to be displayed using a TreeView, you need to have your data in the code-behind to be in that hierarchy. Using a grouped CollectionViewSource is fine, but remember that it is a generic object which does not come with IsSelected and IsExpanded properties on each tier. To track those, you'll need to create your own objects. – Rachel Sep 27 '11 at 16:52