Search code examples
wpftemplatesxamltriggerscelltemplate

How to trigger cellTemplateSelector when Items changed


I have 2 templates for DataGrid's CellTemplate. When I change the items, it won't help me select the template for me, my DisplayModeTemplateSelector won't even be called!

What I'm wondering is if there is a way to trigger this CellTemplateSelector again when items changed? How to refresh CellTemplate in DataGrid or ListView When Content Changes

<DataGridTemplateColumn x:Name="colorRange"
                        Width="*"
                        Header="Color Range">
    <DataGridTemplateColumn.CellTemplateSelector>
        <local:DisplayModeTemplateSelector HeatMapTemplate="{StaticResource heatMapTemplate}" ThreshHoldTemplate="{StaticResource threshHoldTemplate}" />
    </DataGridTemplateColumn.CellTemplateSelector>
</DataGridTemplateColumn>

I found this blog http://dotdotnet.blogspot.com/2008/11/refresh-celltemplate-in-listview-when.html

I think this is similar with my problem, but I really can't understand him! Can anyone explain it?


Solution

  • The solution in the blog post will not work with the DataGrid control because the DataGridTemplateColumn class doesn't belong to the Visual Tree, and even when I tried to bind it to a static class, I didn't suceed because of strange exceptions after property changes.

    Anyway there is two possible ways to solve this problem.

    1) The easier way.

    Using the ObservableCollection class.

        var itemIndex = 0;
        var currentItem = vm.Items[itemIndex];
        //Change necessary properties
        //..
        vm.Items.Remove(currentItem);
        vm.Items.Insert(itemIndex, currentItem);      
    

    2) The more complex way.

    You can add to your item class the property which returns the object itself.

        public ItemViewModel(/*...*/)
        {
            this.SelfProperty = this;
            //...
        }
    
        public ItemViewModel SelfProperty { get; private set; }
    
        public void Update()
        {
            this.SelfProperty = null;
            this.OnPropertyChanged("SelfProperty");
            this.SelfProperty = this;
            this.OnPropertyChanged("SelfProperty");
        }
    

    After that you can use the ContentControl.ContentTemplateSelector instead of the CellTemplateSelector like this:

                <DataGridTemplateColumn Header="Color Range">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ContentControl Content="{Binding SelfProperty}"  ContentTemplateSelector="{StaticResource mySelector}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
    

    And when you change the property, call the Update method somehow:

      currentItem.SomeDataProperty = "some new value";
      //Or you can add this method call to the OnPropertyChanged 
      //so that it calls authomatically
      currentItem.Update(); 
    

    The reason why I've set a null value to the SelfProperty in the Update method first, is that the Selector will not update a template until the Content property is completely changed. If I set the same object once again - nothing will happen, but if I set a null value to it first - changes will be handled.