ashchuk
ashchuk

Reputation: 331

How to update UWP pivot appearence using MVVM pattern

I'm developing UWP app using MVVM pattern. There is a Pivot control on the page, here is a gist. It looks like this:

enter image description here

I need to highlight a pivot element header and list element then user select an answer. Like this:

enter image description here

And I have a problem with updating pivot header and sublist appearence. I tried to subscribe for different Pivot events, like LayoutUpdated, Loaded, PivotItemLoaded and others, but this way did not solve the problem.

It seems like all pivot elements are loaded once when page is created. I have achieved that header highlights then page reloaded or renavigated, but this is not what I need.

How can I update Pivot header appearence and other elements?

Upvotes: 0

Views: 368

Answers (1)

Nico Zhu
Nico Zhu

Reputation: 32775

It seems like all pivot elements are loaded once when page is created. I have achieved that header highlights then page reloaded or renavigated, but this is not what I need. How can I update Pivot header appearence and other elements?

For your requirement, you have to create logical data model. enter image description here

The DataContext of PivotHeader is "Question". So you could make IsCheck Property for PivotHeader in the Question class. And the DataContext of listView item is "Answer". So you could make 'IsRightFlag' property for listview item. This is a typical sandwich architecture.

ViewModel.cs

public class MainPageViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    private ObservableCollection<Question> questions;
    public ObservableCollection<Question> Questions { get => questions; set => questions = value; }

    public MainPageViewModel()
    {
        questions = new ObservableCollection<Question>();
        this.Questions.Add(new Question { Text = "Hello This Nico !", QuestionNumber = "1", RightAnswer = new Answer { Text = "Nico" } });
        this.Questions.Add(new Question { Text = "Hello This Sunteen !", QuestionNumber = "2", RightAnswer = new Answer { Text = "Sunteen" } });
        this.Questions.Add(new Question { Text = "Hello This Lidong !", QuestionNumber = "3", RightAnswer = new Answer { Text = "Lidong" } });
    }
} 

Question.cs

public class Question : INotifyPropertyChanged
    {
        public string QuestionNumber { get; set; }
        public string Text { get; set; }
        public Answer RightAnswer { get; set; }
        public ObservableCollection<Answer> Answers { get => answers; set => answers = value; }
        public void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private ObservableCollection<Answer> answers;
        private Question CurrentQuestion;
        public event PropertyChangedEventHandler PropertyChanged;
        private Answer selectItem;
        public Answer SelectItem
        {
            get
            {
                return selectItem;
            }
            set
            {
                selectItem = value;

                if (selectItem.Text == CurrentQuestion.RightAnswer.Text)
                {
                    selectItem.IsRightFlag = true;
                    IsCheck = true;
                }
                else
                {
                    selectItem.IsRightFlag = false;
                    IsCheck = false;
                }
                OnPropertyChanged();
            }
        }
        private bool isCheck;
        public bool IsCheck
        {
            get
            {
                return isCheck;
            }
            set
            {
                isCheck = value;
                OnPropertyChanged();
            }
        }
        public ICommand ItemCommand
        {
            get
            {
                return new CommadEventHandler<Question>((item) => ItemClick(item));
            }
        }
        private void ItemClick(Question item)
        {
            this.CurrentQuestion = item;
        }
        public Question()
        {
            answers = new ObservableCollection<Answer>();
            Answers.Add(new Answer { Text = "Lidong" });
            Answers.Add(new Answer { Text = "Nico" });
            Answers.Add(new Answer { Text = "Sunteen" });
            Answers.Add(new Answer { Text = "Who ?" });
        }
    }

Answer.cs

public class Answer : INotifyPropertyChanged
{
    public string Text { get; set; }
    private bool isRigntFlag;
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    public bool IsRightFlag
    {
        get
        {
            return isRigntFlag;
        }
        set
        {
            isRigntFlag = value;
            OnPropertyChanged();
        }
    }
}

MainPage.xaml

<Page.DataContext>
    <local:MainPageViewModel/>
</Page.DataContext>
<Page.Resources>
    <local:WaringConverter x:Key="converter"/>
    <DataTemplate x:Key="AnswerListDataTemplate">
        <Border Margin="5" BorderThickness="2" BorderBrush="White" Background="Transparent"
                DataContext="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}">
            <TextBlock 
                Margin="10" 
                FontSize="28" 
                TextWrapping="WrapWholeWords" 
                Text="{Binding Text}"
                Foreground="{Binding IsRightFlag, Converter={StaticResource converter},Mode=TwoWay}"/>
        </Border>
    </DataTemplate>
    <DataTemplate x:Key="PivotQuestionDataTemplate">
        <StackPanel Orientation="Vertical">
            <TextBlock FontSize="28" Margin="20" TextWrapping="WrapWholeWords" Text="{Binding Text}"/>
            <ListView Grid.Row="2" Margin="0,10" IsItemClickEnabled="True"                  
                          ItemsSource="{Binding Answers}"  
                          SelectedItem="{Binding SelectItem,Mode=TwoWay}"
                          ItemTemplate="{StaticResource AnswerListDataTemplate}"
                      >
                <i:Interaction.Behaviors>
                    <ic:EventTriggerBehavior EventName="ItemClick">
                        <ic:InvokeCommandAction  Command="{Binding ItemCommand}" CommandParameter="{Binding}" />
                    </ic:EventTriggerBehavior>
                </i:Interaction.Behaviors>
            </ListView>
        </StackPanel>
    </DataTemplate>
    <DataTemplate x:Key="PivotHeaderDataTemplate">
        <Border Padding="5" BorderThickness="2" BorderBrush="Gray" Background="{Binding IsCheck ,Converter={StaticResource converter},Mode=TwoWay}">
            <TextBlock FontSize="24" >
                <Run x:Uid="QuestionsPage/QuestionNumber"/>
                <Run Text="{Binding QuestionNumber}"/>
            </TextBlock>
        </Border>
    </DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid Margin="30,50,30,10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Text=""/>
        <Pivot Grid.Row="2"
               x:Name="pivotControl"

               ItemsSource="{Binding Questions}" 
               ItemTemplate="{StaticResource PivotQuestionDataTemplate}"
               HeaderTemplate="{StaticResource PivotHeaderDataTemplate}" 
               >
        </Pivot>
    </Grid>
</Grid>

WaringConverter.cs

public class WaringConverter :IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            if((bool)value == true)
            {
                return new SolidColorBrush(Colors.Green);
            }
            else
            {
                return new SolidColorBrush(Colors.Gray);
            }  
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }

enter image description here

Upvotes: 2

Related Questions