Как вызвать cellTemplateSelector при изменении элементов - PullRequest
4 голосов
/ 25 сентября 2011

У меня есть 2 шаблона для CellTemplate DataGrid.Когда я изменяю элементы, это не поможет мне выбрать шаблон для меня, мой DisplayModeTemplateSelector даже не будет вызываться!

Мне интересно, есть ли способ снова вызвать этот CellTemplateSelector, когдаэлементы изменились?Как обновить CellTemplate в DataGrid или ListView при изменении содержимого

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

Я нашел этот блог http://dotdotnet.blogspot.com/2008/11/refresh-celltemplate-in-listview-when.html

Я думаю, что это похоже на мою проблему, но я действительно не понимаю его!Кто-нибудь может это объяснить?

Ответы [ 2 ]

3 голосов
/ 25 сентября 2011

Решение в посте блога не будет работать с элементом управления DataGrid, поскольку класс DataGridTemplateColumn не относится к дереву визуалов, и даже когда я пытался связать его со статическим классом, я не делалпреуспеть из-за странных исключений после изменения свойств.

В любом случае есть два возможных способа решения этой проблемы.

1) Более простой способ.

Использование класса ObservableCollection.

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

2) Более сложный способ.

Вы можете добавить в свой класс элементов свойство, которое возвращает сам объект.

    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");
    }

После этого вы можете использовать ContentControl.ContentTemplateSelector вместо CellTemplateSelector следующим образом:

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

А когда вы изменяете свойство, как-то вызывайте метод Update:

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

Причина, по которой я сначала установил нулевое значение для SelfProperty в методе Update, заключается в том, что Selector не будет обновлять шаблон до тех пор, пока свойство Contentполностью изменился.Если я снова установлю тот же объект - ничего не произойдет, но если я сначала установлю для него нулевое значение - изменения будут обработаны.

2 голосов
/ 15 августа 2012

Самый простой способ - перехватить событие «Выбранное изменение в поле со списком» и переназначить селектор шаблона.Это вызывает обновление.

В XAML (предположим, остальная часть 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>

Это относится к этому DataGridTemplateColumn:

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

И в коде позади:

private void GateIDChanged(object sender, SelectionChangedEventArgs eventArgs)
{
    var selector = GateParamsColumn.CellTemplateSelector;
    GateParamsColumn.CellTemplateSelector = null;
    GateParamsColumn.CellTemplateSelector = selector;
}
...