【问题标题】:How to change Gridview Item UI when Observable Collection change object state当 Observable Collection 更改对象状态时如何更改 Gridview 项 UI
【发布时间】:2021-01-02 18:34:50
【问题描述】:

我试图在我的 gridview 中只允许一个切换按钮打开。如果下一个切换,前一个切换按钮必须取消切换。我的 gridview 的结构如下:

  1. GridView 与可观察集合绑定

  2. 在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>
    
  3. 这是我的用户控件的 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>
    
  4. 这是那个 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; }
}

【问题讨论】:

    标签: xaml uwp


    【解决方案1】:

    UI 对IsSelected 属性的更改没有反应的原因是FoodDto 是一个POCO,并且没有实现INotifyPropetyChanged。如果您确保在IsSelected 更改时提高PropertyChanged,它将反映在DataTemplate 中的x:Bind 中,然后也会流入您的UserControl

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多