好的,我已经准备了一个示例来说明这是如何实现的。为了解决 UWP 中的限制,它使用了一些技术,例如“数据上下文锚定”和附加属性。
这是我的支持课程,我认为它们与您的有些相似:
public class GameControllerViewModel : INotifyPropertyChanged
{
private Team _currentTeam;
public event PropertyChangedEventHandler PropertyChanged;
public GameControllerViewModel(IEnumerable<Team> teams)
{
Teams = teams;
}
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public Team CurrentTeam
{
get { return _currentTeam; }
set
{
if (value != _currentTeam)
{
_currentTeam = value;
OnPropertyChanged();
}
}
}
public IEnumerable<Team> Teams { get; private set; }
}
public class Team
{
public string Name { get; set; }
}
以及页面背后的代码:
public sealed partial class GamesPage : Page
{
public GamesPage()
{
this.InitializeComponent();
this.DataContext = new GameControllerViewModel(
new[]
{
new Team { Name = "Team A" },
new Team { Name = "Team B" },
new Team { Name = "Team C" },
new Team { Name = "Team D" }
}
);
}
}
如你所见,页面的构造函数实例化了一个有四个团队的GameControllerViewModel,并将其设置为页面的数据上下文。
页面XAML如下:
<Page
x:Class="UniversalScratchApp.GamesPage" x:Name="View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UniversalScratchApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<local:BoolToFontWeightConverter x:Key="BoolToFontWeightConverter"/>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Current Team:" Margin="4" VerticalAlignment="Center"/>
<ComboBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding Teams}" SelectedItem="{Binding CurrentTeam, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Stretch" Margin="4">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ItemsControl Grid.Row="1" Grid.ColumnSpan="2" ItemsSource="{Binding Teams}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" local:TeamProperties.CurrentTeam="{Binding ElementName=View, Path=DataContext.CurrentTeam}" local:TeamProperties.Team="{Binding}" FontWeight="{Binding Path=(local:TeamProperties.IsCurrentTeam), RelativeSource={RelativeSource Mode=Self}, Mode=OneWay, Converter={StaticResource BoolToFontWeightConverter}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Page>
在 ItemsControl 的 DataTemplate 中,您可以看到我绑定到三个自定义附加属性; TeamProperties.CurrentTeam、TeamProperties.Team 和 TeamProperties.IsCurrentTeam。附加属性在以下类中定义:
[Bindable]
public static class TeamProperties
{
private static void TeamPropertiesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
Team team = GetTeam(sender);
Team currentTeam = GetCurrentTeam(sender);
if (team != null && currentTeam != null)
{
SetIsCurrentTeam(sender, team.Equals(currentTeam));
}
}
public static readonly DependencyProperty CurrentTeamProperty = DependencyProperty.RegisterAttached("CurrentTeam", typeof(Team), typeof(TeamProperties), new PropertyMetadata(null, TeamPropertiesChanged));
public static Team GetCurrentTeam(DependencyObject obj)
{
return (Team)obj.GetValue(CurrentTeamProperty);
}
public static void SetCurrentTeam(DependencyObject obj, Team value)
{
obj.SetValue(CurrentTeamProperty, value);
}
public static readonly DependencyProperty TeamProperty = DependencyProperty.RegisterAttached("Team", typeof(Team), typeof(TeamProperties), new PropertyMetadata(null, TeamPropertiesChanged));
public static Team GetTeam(DependencyObject obj)
{
return (Team)obj.GetValue(TeamProperty);
}
public static void SetTeam(DependencyObject obj, Team value)
{
obj.SetValue(TeamProperty, value);
}
public static readonly DependencyProperty IsCurrentTeamProperty = DependencyProperty.RegisterAttached("IsCurrentTeam", typeof(bool), typeof(TeamProperties), new PropertyMetadata(false));
public static bool GetIsCurrentTeam(DependencyObject obj)
{
return (bool)obj.GetValue(IsCurrentTeamProperty);
}
public static void SetIsCurrentTeam(DependencyObject obj, bool value)
{
obj.SetValue(IsCurrentTeamProperty, value);
}
}
解释一下,CurrentTeam 和 Team 属性是由绑定在依赖对象(文本块)上设置的。虽然Team 属性可以使用当前数据上下文,但CurrentTeam 属性必须绑定到“外部”数据上下文。它通过在页面上指定 x:Name="View" 并使用它来“锚定”数据上下文来实现此目的,这样就可以通过使用绑定的 ElementName=View 部分的绑定来访问它。
因此,只要这些属性中的任何一个发生更改,TeamPropertiesChanged 回调就会在同一依赖对象上设置 IsCurrentTeam 属性。然后,IsCurrentTeam 属性将绑定到 FontWeight 属性(因为它比下划线更容易),此处显示的 BoolToFontWeightConverter:
public class BoolToFontWeightConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is bool)
{
return ((bool)value) ? FontWeights.ExtraBold : FontWeights.Normal;
}
else
{
return DependencyProperty.UnsetValue;
}
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotSupportedException();
}
}
现在,当在顶部组合框中选择了一个团队(代表您用于更改团队的任何机制)时,ItemsControl 中的相应团队将以粗体显示。
对我来说很好用。希望对您有所帮助。