目前,我有一个与此类似的问题
How can I stop a Toggled Event on a switch from being fired as a page is loaded?
除了我的错误外,当我切换我的开关时,它会在InitGroupMethod处导致无限循环。这是因为我在此期间以编程方式更改了切换事件。再次触发toggleEvent。我想发生的是,当禁用类别时,将不再添加所有底部类别,并且将刷新页面。
当前在打开页面时正确加载,并且如果保存列表然后重新访问它。但是,当切换无穷大循环时,无法更新视图。
此处的图片https://gyazo.com/eedd4ab2ab3cd892ef57cd2d245d7dd1?token=d39388a4b5b726f6c5e2f44219dd4b6f
如何获取视图更新?我试图在更改此事件之前导致自定义切换单元和从toggleEvent取消订阅,但由于它是一个列表,因此无法访问x:name。我也尝试过将其转换为切换单元。xa
brandsviewmodel列表
public class BrandViewModel : ObservableCollection<SubBrandViewModel>, INotifyPropertyChanged
{
private bool isEnabledBrand;
public event PropertyChangedEventHandler PropertyChanged;
public string HouseCode { get; set; }
public List<SubBrandViewModel> SubBrands { get; set; }
public bool IsEnabledBrand
{
get => isEnabledBrand;
set
{
isEnabledBrand = value;
NotifyPropertyChanged();
}
}
}
PageViewModel
public ObservableCollection<Grouping<BrandViewModel, SubBrandViewModel>> GroupedItems { get; set; }
public List<BrandViewModel> Categories { get; set; }
public List<string> AllowedBrands { get; set; }
public List<string> AllowedSubBrands { get; set; }
public void ComputeUiBrandStatus()
{
Dictionary<string, bool> tableWithStrings = new Dictionary<string, bool>();
foreach (string code in AllowedBrands)
{
if (!tableWithStrings.ContainsKey(code))
{
tableWithStrings.Add(code, true);
}
}
foreach (BrandViewModel category in Categories)
{
if (tableWithStrings.ContainsKey(category.HouseCode))
{
category.IsEnabledBrand = true;
}
if (category.SubBrands != null)
{
foreach (SubBrandViewModel subCategory in category.SubBrands)
{
if (tableWithStrings.ContainsKey(subCategory.Code))
{
subCategory.IsEnabledSubBrand = true;
}
}
}
}
}
private void InitGrouppedData()
{
GroupedItems.Clear();
var items = new ObservableCollection<Grouping<BrandViewModel, SubBrandViewModel>>();
foreach (BrandViewModel category in Categories)
{
List<SubBrandViewModel> subCategory = new List<SubBrandViewModel>();
if (category.SubBrands != null && category.IsEnabledBrand)
{
subCategory.AddRange(category.SubBrands);
}
Grouping<BrandViewModel, SubBrandViewModel> group = new Grouping<BrandViewModel, SubBrandViewModel>(category, subCategory);
items.Add(group);
}
GroupedItems = items;
}
private void OnToggleSwitch(object obj)
{
RemoveOrAddSubBrands();
}
页面
<ListView
ItemsSource="{Binding GroupedItems}"
IsGroupingEnabled="True"
GroupDisplayBinding="{Binding Key.HouseCode}"
GroupShortNameBinding="{Binding Key.HouseCode}"
HasUnevenRows="False"
Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" HorizontalOptions="FillAndExpand"
SelectionMode="None">
<ListView.GroupHeaderTemplate >
<DataTemplate>
<ViewCell >
<FlexLayout Direction="Row" JustifyContent="SpaceBetween">
<FlexLayout.Triggers>
<DataTrigger TargetType="FlexLayout" Binding="{Binding Source={x:Reference SwitchParent}, Path=IsToggled}" Value="True">
<Setter Property="BackgroundColor" Value="{StaticResource ThemeBkColor}" />
</DataTrigger>
</FlexLayout.Triggers>
<Label Text="{Binding Key.HouseCode}" VerticalOptions="Center" VerticalTextAlignment="Center" Margin="20,0,0,0" >
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding Source={x:Reference SwitchParent},Path=IsToggled}" Value="True">
<Setter Property="TextColor" Value="White" />
</DataTrigger>
</Label.Triggers>
</Label>
<Switch x:Name="SwitchParent" IsToggled="{Binding Key.IsEnabledBrand}" >
<Switch.Behaviors>
<controls:EventToCommandBehavior EventName="Toggled" Command="{Binding Source={x:Reference BrandPage}, Path=ViewModel.SwitchToggledCommand}" CommandParameter="{Binding .}"/>
</Switch.Behaviors>
</Switch>
</FlexLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<FlexLayout Direction="Row" JustifyContent="SpaceBetween" Margin="30,0,0,0">
<FlexLayout.Triggers>
<DataTrigger TargetType="FlexLayout" Binding="{Binding Source={x:Reference Switch}, Path=IsToggled}" Value="True">
<Setter Property="BackgroundColor" Value="{StaticResource ThemeBkColor}" />
</DataTrigger>
</FlexLayout.Triggers>
<Label Text="{Binding Code}" VerticalOptions="Center" VerticalTextAlignment="Center" Margin="20,0,0,0" >
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding Source={x:Reference Switch},Path=IsToggled}" Value="True">
<Setter Property="TextColor" Value="White" />
</DataTrigger>
</Label.Triggers>
</Label>
<Switch x:Name="Switch" IsToggled="{Binding IsEnabledSubBrand}" />
</FlexLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
答案 0 :(得分:1)
在为调用PropertyChanged的属性编写设置器时,请保护事件的实际更新和信令:
public bool IsEnabledBrand
{
get => isEnabledBrand;
set
{
if (isEnabledBrand != value)
{
isEnabledBrand = value;
NotifyPropertyChanged();
}
}
}
要点是,除非属性发生更改,否则您不希望引发OnPropertyChanged事件。您的代码不足以知道这是否是问题,但是值得牢记此设计要点,因为它可以避免出现问题。
答案 1 :(得分:1)
只要为我的特定循环开关问题添加解决方案,以防其他类似情况的人受益:
我只需要确保我的切换事件处理程序使用的是事件args,而不是IsToggled
绑定变量。
更改自:
async void ToggleFollow(object sender, ToggledEventArgs args) {
if (viewModel.UserIsFollowingOwner) {
await viewModel.UnFollowOwner();
} else {
await viewModel.FollowOwner();
}
}
收件人:
async void ToggleFollow(object sender, ToggledEventArgs args) {
if (args.Value) {
await viewModel.FollowOwner();
} else {
await viewModel.UnFollowOwner();
}
}