Xamarin 布尔转换器:尽管通过了转换器,但不更新页面
Xamarin Boolean converter: does not update page despite going through the converter
我正在尝试为我的页面使用转换器,但无济于事。
页面的重要部分是一个开关,两个列表视图。这些 Listview 是一个在另一个上面,根据开关的状态,应该只显示其中一个。在少数情况下,开关的状态也应该可以从应用程序中更改。
为此,我有一个布尔值 属性 (isPrimaryBin),如果为真,第一个列表视图 (primaryBinListView) 应该可见,第二个列表视图 (secondaryBinListView) 应该隐藏。
当 isPrimaryBin 变为 false 时,secondaryBinListview 可见,primaryListView 隐藏。
最后一件事,为了使其更直观,重要的是开关不应在 isPrimaryBin 为真时切换,而在 isPrimaryBin 为假时切换。 (由于标签在开关的两侧,它象征着从一个垃圾箱到另一个垃圾箱的开关)
起初我尝试创建第二个 属性,它会输出与 isPrimaryBin 相反的内容,但我永远不会点击 onPropertyChanged。所以我学会了如何制作转换器并制作了一个。起初,它不会击中它。我摆弄它,意识到我必须将它添加到资源字典中。然后它开始自己循环。页面陷入无限循环。我设法阻止了这种行为,但现在它不再更新页面。尽管开关已更改,但 primaryBinListview 始终可见,而 secondaryBinListView 始终隐藏。开关改变状态。它确实通过 属性。它确实通过转换器。我不知道为什么在它清楚地完成所有步骤时没有任何变化。
现在进入代码。让我们从 属性:
开始
public bool isPrimaryBin {
get { return _isPrimaryBin; }
set {
if (_isPrimaryBin != value) {
_isPrimaryBin = value;
OnPropertyChanged();
}
}
}
然后转换器
public class inverseBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return !((bool)value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return !(bool)value;
}
}
最后是相关的Xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Picking.Views.Inv2Page"
Title="{Binding Title}"
xmlns:local="clr-namespace:Picking.Helpers">
<ContentPage.Resources>
<ResourceDictionary>
<local:inverseBoolConverter x:Key="inverseBoolConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<Grid RowSpacing="0">
<Grid Grid.Row="0">
<Switch Grid.Column="1" OnColor="Orange" ThumbColor="Gray" IsVisible="{Binding isMoveGoods}" IsToggled="{Binding isPrimaryBin, Mode=TwoWay, Converter={StaticResource inverseBoolConverter}}"/
</Grid>
<ListView x:Name="ItemsListView" Grid.Row="1"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadItemsCommand}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement"
ItemTapped="ItemsListView_ItemTapped"
Grid.RowSpan="2"
IsVisible="{Binding isPrimaryBin}"
>
</ListView>
<ListView x:Name="ItemsListViewTransfer" Grid.Row="1"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadItemsCommand}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement"
ItemTapped="ItemsListView_ItemTapped"
Grid.RowSpan="2"
IsVisible="{Binding isPrimaryBin, Converter={StaticResource inverseBoolConverter}}"
>
</ListView>
</ContentPage.Content>
</ContentPage>
我删除了与问题无关的任何内容(例如,列表视图的内容、额外的标签或与我的问题无关的任何内容)
这是我第一次使用转换器。我查看了关于如何使它们工作的多个指南,当没有任何工作但至少没有中断时,它让我陷入了这个奇怪的困境。
感谢您的帮助。
看起来你的两个 listView 在开关状态改变时加载相同的数据,所以看起来 UI 不会 change.Maybe 你可以显示你的 viewmodel.That更清晰。
下面是一个包含您的代码的简单示例,如果您想要的话?
ConvertModel(您可以更换自己的视图模型):
class ConvertModel :INotifyPropertyChanged
{
ObservableCollection<string> items = new ObservableCollection<string>();
public ObservableCollection<string> Items { get { return items; } }
private bool _isPrimaryBin;
public bool isPrimaryBin
{
get { return _isPrimaryBin; }
set
{
_isPrimaryBin = value;
if (_isPrimaryBin)
{
items.Clear();
items.Add("aaa");
items.Add("bbb");
items.Add("ccc");
items.Add("ddd");
items.Add("eee");
items.Add("fff");
items.Add("ggg");
}
else
{
items.Clear();
items.Add("111");
items.Add("222");
items.Add("333");
items.Add("444");
items.Add("555");
items.Add("666");
items.Add("777");
}
OnPropertyChanged();
}
}
public ConvertModel(bool isPr)
{
_isPrimaryBin = isPr;
if (isPr)
{
items.Add("aaa");
items.Add("bbb");
items.Add("ccc");
items.Add("ddd");
items.Add("eee");
items.Add("fff");
items.Add("ggg");
}
else
{
items.Add("111");
items.Add("222");
items.Add("333");
items.Add("444");
items.Add("555");
items.Add("666");
items.Add("777");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
page.xaml:
<ContentPage.Resources>
<ResourceDictionary>
<local:inverseBoolConverter x:Key="inverseBoolConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<Switch Grid.Column="1" OnColor="Orange" ThumbColor="Gray" IsToggled="{Binding isPrimaryBin, Mode=TwoWay, Converter={StaticResource inverseBoolConverter}}"></Switch>
<ListView x:Name="ItemsListView"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
IsPullToRefreshEnabled="true"
CachingStrategy="RecycleElement"
IsVisible="{Binding isPrimaryBin}"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding .}"></Label>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView x:Name="ItemsListViewTransfer"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
IsPullToRefreshEnabled="true"
CachingStrategy="RecycleElement"
IsVisible="{Binding isPrimaryBin, Converter={StaticResource inverseBoolConverter}}"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding .}"></Label>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
page.xaml.cs:
public ConvertPage()
{
InitializeComponent();
ConvertModel convertModel = new ConvertModel(false);
BindingContext = convertModel;
}
效果如:
我正在尝试为我的页面使用转换器,但无济于事。
页面的重要部分是一个开关,两个列表视图。这些 Listview 是一个在另一个上面,根据开关的状态,应该只显示其中一个。在少数情况下,开关的状态也应该可以从应用程序中更改。
为此,我有一个布尔值 属性 (isPrimaryBin),如果为真,第一个列表视图 (primaryBinListView) 应该可见,第二个列表视图 (secondaryBinListView) 应该隐藏。
当 isPrimaryBin 变为 false 时,secondaryBinListview 可见,primaryListView 隐藏。
最后一件事,为了使其更直观,重要的是开关不应在 isPrimaryBin 为真时切换,而在 isPrimaryBin 为假时切换。 (由于标签在开关的两侧,它象征着从一个垃圾箱到另一个垃圾箱的开关)
起初我尝试创建第二个 属性,它会输出与 isPrimaryBin 相反的内容,但我永远不会点击 onPropertyChanged。所以我学会了如何制作转换器并制作了一个。起初,它不会击中它。我摆弄它,意识到我必须将它添加到资源字典中。然后它开始自己循环。页面陷入无限循环。我设法阻止了这种行为,但现在它不再更新页面。尽管开关已更改,但 primaryBinListview 始终可见,而 secondaryBinListView 始终隐藏。开关改变状态。它确实通过 属性。它确实通过转换器。我不知道为什么在它清楚地完成所有步骤时没有任何变化。
现在进入代码。让我们从 属性:
开始public bool isPrimaryBin {
get { return _isPrimaryBin; }
set {
if (_isPrimaryBin != value) {
_isPrimaryBin = value;
OnPropertyChanged();
}
}
}
然后转换器
public class inverseBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return !((bool)value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return !(bool)value;
}
}
最后是相关的Xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Picking.Views.Inv2Page"
Title="{Binding Title}"
xmlns:local="clr-namespace:Picking.Helpers">
<ContentPage.Resources>
<ResourceDictionary>
<local:inverseBoolConverter x:Key="inverseBoolConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<Grid RowSpacing="0">
<Grid Grid.Row="0">
<Switch Grid.Column="1" OnColor="Orange" ThumbColor="Gray" IsVisible="{Binding isMoveGoods}" IsToggled="{Binding isPrimaryBin, Mode=TwoWay, Converter={StaticResource inverseBoolConverter}}"/
</Grid>
<ListView x:Name="ItemsListView" Grid.Row="1"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadItemsCommand}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement"
ItemTapped="ItemsListView_ItemTapped"
Grid.RowSpan="2"
IsVisible="{Binding isPrimaryBin}"
>
</ListView>
<ListView x:Name="ItemsListViewTransfer" Grid.Row="1"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadItemsCommand}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement"
ItemTapped="ItemsListView_ItemTapped"
Grid.RowSpan="2"
IsVisible="{Binding isPrimaryBin, Converter={StaticResource inverseBoolConverter}}"
>
</ListView>
</ContentPage.Content>
</ContentPage>
我删除了与问题无关的任何内容(例如,列表视图的内容、额外的标签或与我的问题无关的任何内容)
这是我第一次使用转换器。我查看了关于如何使它们工作的多个指南,当没有任何工作但至少没有中断时,它让我陷入了这个奇怪的困境。
感谢您的帮助。
看起来你的两个 listView 在开关状态改变时加载相同的数据,所以看起来 UI 不会 change.Maybe 你可以显示你的 viewmodel.That更清晰。
下面是一个包含您的代码的简单示例,如果您想要的话?
ConvertModel(您可以更换自己的视图模型):
class ConvertModel :INotifyPropertyChanged
{
ObservableCollection<string> items = new ObservableCollection<string>();
public ObservableCollection<string> Items { get { return items; } }
private bool _isPrimaryBin;
public bool isPrimaryBin
{
get { return _isPrimaryBin; }
set
{
_isPrimaryBin = value;
if (_isPrimaryBin)
{
items.Clear();
items.Add("aaa");
items.Add("bbb");
items.Add("ccc");
items.Add("ddd");
items.Add("eee");
items.Add("fff");
items.Add("ggg");
}
else
{
items.Clear();
items.Add("111");
items.Add("222");
items.Add("333");
items.Add("444");
items.Add("555");
items.Add("666");
items.Add("777");
}
OnPropertyChanged();
}
}
public ConvertModel(bool isPr)
{
_isPrimaryBin = isPr;
if (isPr)
{
items.Add("aaa");
items.Add("bbb");
items.Add("ccc");
items.Add("ddd");
items.Add("eee");
items.Add("fff");
items.Add("ggg");
}
else
{
items.Add("111");
items.Add("222");
items.Add("333");
items.Add("444");
items.Add("555");
items.Add("666");
items.Add("777");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
page.xaml:
<ContentPage.Resources>
<ResourceDictionary>
<local:inverseBoolConverter x:Key="inverseBoolConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<Switch Grid.Column="1" OnColor="Orange" ThumbColor="Gray" IsToggled="{Binding isPrimaryBin, Mode=TwoWay, Converter={StaticResource inverseBoolConverter}}"></Switch>
<ListView x:Name="ItemsListView"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
IsPullToRefreshEnabled="true"
CachingStrategy="RecycleElement"
IsVisible="{Binding isPrimaryBin}"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding .}"></Label>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView x:Name="ItemsListViewTransfer"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
IsPullToRefreshEnabled="true"
CachingStrategy="RecycleElement"
IsVisible="{Binding isPrimaryBin, Converter={StaticResource inverseBoolConverter}}"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding .}"></Label>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
page.xaml.cs:
public ConvertPage()
{
InitializeComponent();
ConvertModel convertModel = new ConvertModel(false);
BindingContext = convertModel;
}
效果如: