Pergunta

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?

Foi útil?

Solução

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.

Outras dicas

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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top