【发布时间】:2021-01-02 18:34:50
【问题描述】:
我试图在我的 gridview 中只允许一个切换按钮打开。如果下一个切换,前一个切换按钮必须取消切换。我的 gridview 的结构如下:
-
GridView 与可观察集合绑定
-
在gridview 内容中,用户控件代表gridview 项
<controls:AdaptiveGridView.ItemTemplate> <DataTemplate x:DataType="data:FoodDTO"> <usercontrols:FoodCard FoodId="{x:Bind FoodId}" FoodName="{x:Bind FoodName}" FoodEnglishName="{x:Bind FoodEnglishName}" IsSelected="{Binding IsSelected, Mode=TwoWay}" MainFoodIcon="{x:Bind MainIcon}" SecondaryFoodIcon="{x:Bind SecondaryIcon}" ToggleClick="FoodCard_ToggleClick"/> </DataTemplate> </controls:AdaptiveGridView.ItemTemplate> -
这是我的用户控件的 XAML
<Grid Height="130" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Margin="5" Padding="0"> <ToolkitControls:DropShadowPanel x:Name="DropShadowHolder" VerticalAlignment="Stretch" Margin="10" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" BlurRadius="20" ShadowOpacity="0.5" OffsetX="1" OffsetY="20" Color="Black"> <Grid Background="{ThemeResource SystemAltHighColor}" Height="100" CornerRadius="5" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Padding="0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="80"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <ToggleButton Content="CHỌN" FontWeight="Bold" Click="ToggleButton_Click" IsChecked="{Binding IsSelected, Mode=TwoWay}" VerticalAlignment="Bottom" Margin="10,0,0,10" Width="70" FontSize="12"/> <Grid Grid.Column="1" VerticalAlignment="Bottom" Margin="11"> <StackPanel VerticalAlignment="Bottom"> <TextBlock Text="40%" /> <ProgressBar Height="30" CornerRadius="3" Value="40"/> </StackPanel> <PersonPicture Width="25" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,-10,0,0"/> </Grid> <TextBlock Text="{x:Bind FoodName, Mode=OneWay}" Grid.Column="1" Margin="6,0,0,0" FontSize="15" /> </Grid> </ToolkitControls:DropShadowPanel> <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left"> <Grid Margin="20,0,0,0"> <Image x:Name="MainFoodImage" Width="70" Height="70" VerticalAlignment="Center" HorizontalAlignment="Center"/> <Image x:Name="SecondaryFoodImage" Width="20" Height="20" VerticalAlignment="Top" HorizontalAlignment="Right"/> </Grid> <TextBlock Text="{x:Bind FoodEnglishName, Mode=OneWay}" VerticalAlignment="Top" Margin="6,-5,0,0" FontSize="15" FontWeight="Bold" /> </StackPanel> -
这是那个 UserControl 背后的代码
公共密封部分类 FoodCard : UserControl, INotifyPropertyChanged {
public int FoodId { get { return (int)GetValue(FoodIdProperty); } set { SetValue(FoodIdProperty, value); } } // Using a DependencyProperty as the backing store for FoodId. This enables animation, styling, binding, etc... public static readonly DependencyProperty FoodIdProperty = DependencyProperty.Register("FoodId", typeof(int), typeof(FoodCard), null); public string FoodName { get { return (string)GetValue(FoodNameProperty); } set { SetValue(FoodNameProperty, value); } } // Using a DependencyProperty as the backing store for FoodName. This enables animation, styling, binding, etc... public static readonly DependencyProperty FoodNameProperty = DependencyProperty.Register("FoodName", typeof(string), typeof(FoodCard), null); public string FoodEnglishName { get { return (string)GetValue(FoodEnglishNameProperty); } set { SetValue(FoodEnglishNameProperty, value); } } // Using a DependencyProperty as the backing store for FoodEnglishName. This enables animation, styling, binding, etc... public static readonly DependencyProperty FoodEnglishNameProperty = DependencyProperty.Register("FoodEnglishName", typeof(string), typeof(FoodCard), null); public bool IsSelected { get { return (bool)GetValue(IsSelectedProperty); } set { SetValue(IsSelectedProperty, value); if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("IsSelected")); } } } // Using a DependencyProperty as the backing store for IsSelected. This enables animation, styling, binding, etc... public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(FoodCard), new PropertyMetadata(null)); public int MainFoodIcon { get { return (int)GetValue(MainFoodIconProperty); } set { SetValue(MainFoodIconProperty, value); MainFoodImage.Source = new BitmapImage(new Uri(_mainFoods[value])); } } // Using a DependencyProperty as the backing store for MainFoodIcon. This enables animation, styling, binding, etc... public static readonly DependencyProperty MainFoodIconProperty = DependencyProperty.Register("MainFoodIcon", typeof(int), typeof(FoodCard), null); public int? SecondaryFoodIcon { get { return (int?)GetValue(SecondaryFoodIconProperty); } set { if(value != null) { SetValue(SecondaryFoodIconProperty, value); SecondaryFoodImage.Source = new BitmapImage(new Uri(_secondaryFoods[value])); } else SecondaryFoodImage.Source = null; } } // Using a DependencyProperty as the backing store for SecondaryFoodIcon. This enables animation, styling, binding, etc... public static readonly DependencyProperty SecondaryFoodIconProperty = DependencyProperty.Register("SecondaryFoodIcon", typeof(int?), typeof(FoodCard), null); private readonly IDictionary<int, string> _mainFoods = new Dictionary<int, string> { { 1, "ms-appx:///Assets/FoodAssets/Rice.png"}, { 2, "ms-appx:///Assets/FoodAssets/Bread.png"}, { 3, "ms-appx:///Assets/FoodAssets/Spagheti.png"}, { 4, "ms-appx:///Assets/FoodAssets/Noodle.png"}, { 5, "ms-appx:///Assets/FoodAssets/LunchFood.png"} }; private readonly IDictionary<int?, string> _secondaryFoods = new Dictionary<int?, string> { { 6, "ms-appx:///Assets/FoodAssets/Meat.png"}, { 7, "ms-appx:///Assets/FoodAssets/Chicken.png"}, { 8, "ms-appx:///Assets/FoodAssets/Egg.png"}, { 9, "ms-appx:///Assets/FoodAssets/Shrimp.png"}, { 10, "ms-appx:///Assets/FoodAssets/Falafel.png"} }; public event FoodCardEventHandler ToggleClick; public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public FoodCard() { this.InitializeComponent(); } private void ToggleButton_Click(object sender, RoutedEventArgs e) { ToggleClick?.Invoke(FoodId); }
挂钩到切换按钮的依赖属性也启用 OnNotifyPropertyChanged
在此代码中,请注意我公开了 ToggleButton_Click 以让包含 gridview 的页面可以处理点击。这就是我的处理方式
private void FoodCard_ToggleClick(int foodId)
{
foreach(FoodDTO dto in Foods)
{
dto.IsSelected = false;
}
foreach (FoodDTO dto in Foods)
{
System.Diagnostics.Debug.WriteLine(dto.IsSelected);
System.Diagnostics.Debug.WriteLine("-------------");
}
}
我在控制台看到它们都输出 IsSelected 为 False,但 ui 元素上的 Toggle Button 没有取消切换。这是FoodDTO
public class FoodDTO
{
public int FoodId { get; set; }
public string FoodName { get; set; }
public string FoodEnglishName { get; set; }
public int MainIcon { get; set; } = 5;
public int? SecondaryIcon { get; set; }
public decimal Percentage { get; set; }
public bool IsSelected { get; set; }
}
【问题讨论】: