Как избежать мерцания при обновлении ContentControl? - PullRequest
0 голосов
/ 18 февраля 2020

У меня есть DataTemplate, определенный как ниже.

        <DataTemplate x:Key="singleUnit">
            <RelativePanel >
                <Button Padding="0,0,0,0" BorderThickness="0" Background="Transparent" Width="180" Height="210" Margin="0,0,70,20"
                        Style="{StaticResource textButtonStyle1}"
                        Command="{Binding ClickCommand}" CommandParameter="{Binding itemIndex}">
                    <StackPanel Orientation="Vertical">
                        <Image Source="{Binding icon_url, Converter={StaticResource _path2Image}}" Width="150" Height="150" Stretch="Uniform" Margin="0,0,0,0"/>
                        <Image Source="ms-appx:///Assets/SettingPage/Selected.png" Width="30" Height="30" Margin="130,-250,0,0"
                               Opacity="{Binding isSelected, Converter={StaticResource _selectedToOpacity}}"/>                           
                    </StackPanel>
                </Button>
            </RelativePanel>
        </DataTemplate>

И я назначу DataTemplate для ContentControl's ContentTemplate. В DataTemplate он содержит два изображения (внутри Button), одно из которых является основным Image, другое - угловой значок (Marker). И каждый раз, когда мне нужно обновить только значок угла: изменить его Opacity на 0 или 1 или наоборот.

Но когда я использую приведенный ниже код для получения этой функции, я иногда нахожу основной Image будет мигать Я нашел какой-то пост от StackOverflow. Кто-то сказал, что это вызвано настройкой триггера Button. Но с помощью Edit Button's Copy я не нахожу сейчас ни одного ключевого слова триггера.

    private void SetMarker(int index)
    {
        ContentControl ccUnit = InitCCUnit(previousSelectedIndex, false);
        wrapGrid.Children[previousSelectedIndex] = ccUnit;

        ccUnit = InitCCUnit(index, true);
        wrapGrid.Children[index] = ccUnit;

        previousSelectedIndex = index;
    }

    private ContentControl InitCCUnit(int index, bool setMarked)
    {
        ContentControl ccUnit = new ContentControl();
        ccUnit.ContentTemplate = this.Resources["singleUnit"] as DataTemplate;

        if (setMarked)
            dms[index].isSelected = true;
        else
            dms[index].isSelected = false;

        ccUnit.Content = dms[index];
        return ccUnit;
    }

Код DataModel: переменная dms - это массив, содержащий экземпляр, если DataModel

    public class DataModel
    {
        public string icon_url { get; set; }
        public int itemIndex { get; set; }
        public bool isSelected { get; set; }
        public ICommand ClickCommand { get; set; }
    }

    DataModel[] dms;

Например, всего 6 изображений. И я щелкаю два из них, названных A и B. Когда я нажимаю A, то отображается значок A (маленький значок галочки) (в то время как изображение A сохраняется); в то же время иконка B скрыта (в то время как изображение B сохраняется). Или наоборот.

Проблема: Здесь, когда значок B скрыт (означает, что я нажимаю на элемент A), иногда изображение B мигает один раз. Не всегда. Почему и как ее решить?

Подробнее: Я делаю демонстрационный проект, чтобы показать эту проблему, пожалуйста, проверьте эту ссылку, чтобы получить код: https://github.com/tomxue/BlinkIssueInUWP.git

Ричард упомянул использование INotifyPropertyChanged, но я не знаю, как объединить его вместе с DataTemplate.

1 Ответ

0 голосов
/ 19 февраля 2020

Я проанализировал ваш код и обнаружил причину мигания.

Основная причина в том, что вы заново создали ContentControl и заменили старый на новый, что не нужно.

Пожалуйста, попробуйте это:

  1. Реализация интерфейса INotifyPropertyChanged для DataModel:
public class DataModel:INotifyPropertyChanged
{
    public string icon_url { get; set; }
    public bool ssml_support { get; set; }
    public string data_name { get; set; }
    public string data_type { get; set; }
    public int itemIndex { get; set; }
    private bool _isSelected;
    public bool isSelected
    {
        get => _isSelected;
        set
        {
            _isSelected = value;
            OnPropertyChanged();
        }
    }
    public ICommand ClickCommand { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName]string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
Переписать SetMarker метод:
private void SetMarker(int index)
{
    ContentControl ccUnit = wrapGrid.Children[previousSelectedIndex] as ContentControl;
    var previousContent = ccUnit.Content as DataModel;
    previousContent.isSelected = false;

    ContentControl currentUnit= wrapGrid.Children[index] as ContentControl;
    var currentContent = currentUnit.Content as DataModel;
    currentContent.isSelected = true;

    previousSelectedIndex = index;
}

Таким образом, нам не нужно создавать новый элемент управления, нам просто нужно изменить состояние старого элемента управления. Это не вызовет так называемую проблему blink.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...