Reputation: 103
I'm trying to only allow one toggle button inside my gridview toggle on. If the next one toggled, the previous toggle button must be de-toggle. the structure of my gridview are these:
GridView bind with an observable collection
Inside a gridview content a user-control represent the gridview item
<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>
Here is the XAML of my User-Control
<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>
Here is the code behind of that UserControl
public sealed partial class 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);
}
The dependency property that hook to the toggle button also enable OnNotifyPropertyChanged
in this code notice that I expose the ToggleButton_Click
to let the Page that contain the gridview can handle the click. And here's how I handle it
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("-------------");
}
}
I watch the console they are all output IsSelected is False, but the Toggle Button on the ui element doesn't de-toggle. Here is the 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; }
}
Upvotes: 1
Views: 53
Reputation: 39102
The reason the UI does not react to the change in IsSelected
property is that the FoodDto
is a POCO, and does not implement INotifyPropetyChanged
. If you make sure to raise PropertyChanged
when IsSelected
changes, it will be reflected in the x:Bind
in the DataTemplate
and will also then flow into your UserControl
.
Upvotes: 2