如何使用 MVVM 模式更新 UWP 枢轴外观
How to update UWP pivot appearence using MVVM pattern
我正在使用 MVVM 模式开发 UWP 应用程序。
页面上有一个Pivot控件,这里是一个gist。它看起来像这样:
我需要突出显示数据透视元素 header 和列表元素,然后用户 select 给出答案。像这样:
而且我在更新枢轴 header 和子列表外观时遇到问题。
我尝试订阅不同的 Pivot 事件,如 LayoutUpdated
、Loaded
、PivotItemLoaded
等,但这种方式并没有解决问题。
创建页面时,似乎所有的枢轴元素都加载了一次。
我已经实现 header 突出显示然后页面重新加载或重新导航,但这不是我需要的。
如何更新 Pivot header 外观和其他元素?
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?
根据您的要求,您必须创建逻辑数据模型。
PivotHeader
的DataContext
是"Question"。因此,您可以在 Question
class 中为 PivotHeader
创建 IsCheck
属性。而 listView 项目的 DataContext
是 "Answer"。所以你可以 'IsRightFlag'
属性 用于列表视图项。这是一个典型的三明治架构。
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();
}
}
我正在使用 MVVM 模式开发 UWP 应用程序。 页面上有一个Pivot控件,这里是一个gist。它看起来像这样:
我需要突出显示数据透视元素 header 和列表元素,然后用户 select 给出答案。像这样:
而且我在更新枢轴 header 和子列表外观时遇到问题。
我尝试订阅不同的 Pivot 事件,如 LayoutUpdated
、Loaded
、PivotItemLoaded
等,但这种方式并没有解决问题。
创建页面时,似乎所有的枢轴元素都加载了一次。 我已经实现 header 突出显示然后页面重新加载或重新导航,但这不是我需要的。
如何更新 Pivot header 外观和其他元素?
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?
根据您的要求,您必须创建逻辑数据模型。
PivotHeader
的DataContext
是"Question"。因此,您可以在 Question
class 中为 PivotHeader
创建 IsCheck
属性。而 listView 项目的 DataContext
是 "Answer"。所以你可以 'IsRightFlag'
属性 用于列表视图项。这是一个典型的三明治架构。
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();
}
}