Domanda

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?

È stato utile?

Soluzione

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.

Altri suggerimenti

The easy way is to hook the Combo Box's Selection Changed event, and reassign the template selector. This forces a refresh.

In XAML (assume the rest of the DataGrid/ComboBoxColumn:

<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
    <Setter Property="ItemsSource" 
            Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}},  Path=DataContext.Gates, UpdateSourceTrigger=PropertyChanged}"/>
    <EventSetter Event="SelectionChanged" Handler="GateIDChanged" />
</Style>

That refers to this DataGridTemplateColumn:

<DataGridTemplateColumn x:Name="GateParamsColumn" Header="Gate Parameters" CellTemplateSelector="{StaticResource GateParamsTemplateSelector}"></DataGridTemplateColumn>

And in the code behind:

private void GateIDChanged(object sender, SelectionChangedEventArgs eventArgs)
{
    var selector = GateParamsColumn.CellTemplateSelector;
    GateParamsColumn.CellTemplateSelector = null;
    GateParamsColumn.CellTemplateSelector = selector;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top