Принуждение ListBox к повторному рендерингу

Фон:

У меня есть ListBox, содержащий элементы, определенные DataTemplates. Прямо сейчас, если у объекта в списке для свойства IsEditable установлено значение true, информация о свойствах элемента будет отображаться внутри текстовых полей (через изменение DataTemplate), а не текстовых блоков (чтобы пользователь мог редактировать содержимое этого элемента списка)

IsEditable включается/выключается кнопкой внутри каждого элемента списка. Мне сказали, что нам нужно поддерживать согласованность состояния всех объектов, а это значит, что я не могу просто перепривязать ItemsSource и потерять все.

В настоящее время я использую это для повторного рендеринга:

this.lbPoints.Dispatcher.Invoke(DispatcherPriority.Render, new Action(() => { }));

Вопрос:

Вышеупомянутый фрагмент кода KIND OF выполняет свою работу. Под «видом» я имею в виду, что в конечном итоге мои данные перерисовываются, но только когда я прокручиваю список до конца, а затем прокручиваю вверх до элемента, который я пытаюсь повторно отобразить.

1) Как я могу немедленно повторно отобразить данные, не прокручивая их, чтобы они отобразились?


person Spencer    schedule 18.03.2014    source источник
comment
Почему бы просто не привязать к TextBox и просто привязать IsReadOnly к IsEditable (вам понадобится другое свойство, которое сбрасывает bool или делает это в конвертере)   -  person paparazzo    schedule 19.03.2014
comment
Вы, вероятно, делаете все это неправильно. Вы должны использовать DataTriggers для динамического изменения содержимого DataTemplates или чего-то еще. Или создайте TextBox, который выглядит как обычный TextBlock, когда IsReadOnly.   -  person Federico Berasategui    schedule 19.03.2014


Ответы (1)


Парни, комментирующие, правы в том, что вы делаете это неправильно... редко возникает необходимость заставить ListBox перерендериться. Вероятно, вы доставляете себе дополнительные неудобства, пытаясь переключить DataTemplate (хотя это возможно). Вместо этого подумайте о привязке данных свойства TextBox.IsReadOnly к вашему свойству IsEditable:

<TextBox IsReadOnly="{Binding IsEditable}" Text="{Binding Text}" />

Другой альтернативой является использование BooleanToVisibilityConverter чтобы показать другой Grid в вашем DataTemplate, когда ваш ресурс IsEditable равен true. К сожалению, у этого Converter нет обратной операции, поэтому вы можете создать свойство IsNotEditing для привязки к Grid в DataTemplate, которое изначально отображается. Я не уверен, что это ясно... см. этот пример:

<DataTemplate DataType="{x:Type YourPrefix:YourDataType}">
    <Grid>
        <Grid Visibility="{Binding IsNotEditing, Converter={StaticResource 
            BooleanToVisibilityConverter}}">
            <!-- Define your uneditable UI here -->
        </Grid>
        <Grid Visibility="{Binding IsEditing, Converter={StaticResource 
            BooleanToVisibilityConverter}}">
            <!-- Define your editable UI here -->
        </Grid>
    </Grid>
</DataTemplate>

Вы также можете определить свой собственный класс BooleanToVisibilityConverter со свойством IsInverted, чтобы можно было использовать только одно свойство IsEditing. Вам нужно будет объявить еще два Converters, например:

<Converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<Converters:BoolToVisibilityConverter x:Key="InvertedBoolToVisibilityConverter" 
    IsInverted="True" />

Тогда ваш XAML будет таким:

<Grid Visibility="{Binding IsEditing, Converter={StaticResource 
    InvertedBoolToVisibilityConverter}}">
    <!-- Define your uneditable UI here -->
</Grid>
<Grid Visibility="{Binding IsEditing, Converter={StaticResource 
    BoolToVisibilityConverter}}">
    <!-- Define your editable UI here -->
</Grid>
person Sheridan    schedule 18.03.2014