xamarin.forms - Xamarin 基于同一 Grid.Row 中的多个绑定属性在 Grid 内设置按钮的 IsVisible 而不编辑原始模型
问题描述
我有一个可以出现在网格的每一行中的按钮。
如果“行”中的任何绑定属性为空,我需要隐藏按钮。
这是使用 MVVM 模式,因此 ViewModel 具有 ObservableCollection。
非常简化的例子:
public class TestClass
{
public int? Prop1 { get; set; }
public int? Prop2 { get; set; }
}
public class TestViewModel
{
private ObservableCollection<TestClass> _TestClasses;
public ObservableCollection<TestClass> TestClasses
{
get { return _TestClasses; }
set { _TestClasses = value; OnPropertyChanged(nameof(TestClasses)); }
}
// LOAD TEST DATA IN CONSTRUCTOR
public TestViewModel()
{
var testClasses = new List<TestClass>();
testClasses.Add(new TestClass { Prop1 = 1, Prop2 = 1 };
testClasses.Add(new TestClass { Prop1 = 2, Prop2 = null };
testClasses.Add(new TestClass { Prop1 = null, Prop2 = 2 };
TestClasses = new ObservableCollection<TestClass>(testClasses);
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class NullBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? false : true;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
当“Prop1”为空时,以下 XAML 将隐藏按钮,但如果“EITHER”Prop1 或 Prop2 为空,我需要隐藏按钮。
<?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:converters="clr-namespace:TestProject.Converters"
x:Class="TestProject">
<ContentPage.Resources>
<ResourceDictionary>
<converters:NullBooleanConverter x:Key="NullBooleanConverter"/>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<ListView ItemsSource="{Binding TestClasses}"
SelectionMode="Single"
HasUnevenRows="True" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="0">
<Label Text="{Binding Prop1}"/>
</StackLayout>
<StackLayout Grid.Column="1">
<Label Text="{Binding Prop2}"/>
</StackLayout>
<StackLayout Grid.Column="2">
<Button Text="Do Something"
IsVisible="{Binding Path=Prop1, Converter={StaticResource NullBooleanConverter}}" />
</StackLayout>
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
更新 1
我无法编辑原始模型,因为它位于其他几个项目中使用的共享库中。
我可以创建模型的部分类,但似乎过于复杂,因为在我们所有其他项目中,这在 UI 中或使用 IMultiValueConverter 很容易实现,但在 Xamarin 中不支持。
更新 2
我在 NullBooleanConverter 中找到了一种“hack”方法。
public class NullBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is TestClass)
{
TestClass testClass = (TestClass)value;
if (testClass.Prop1 == null || testClass.Prop2 == null)
{
return false;
}
else
{
return true;
}
}
else
{
return value;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
解决方案
您还可以将属性IsVisible绑定到 ViewModel
<StackLayout Grid.Column="2">
<Button Text="Do Something"
IsVisible="{Binding isVisible}" />
</StackLayout>
在模型
public class TestClass
{
public string? Prop1 { get; set; }
public string? Prop2 { get; set; }
public bool isVisible { get; private set; }
public TestClass(string? p1,string?p2)
{
if(p1==null||p2==null)
{
isVisible = false;
}
else
{
isVisible = true;
}
}
}
在 ViewModel 中
var testClasses = new List<TestClass>();
testClasses.Add(new TestClass("1","1") );
testClasses.Add(new TestClass(null,"2") );
testClasses.Add(new TestClass("1",null));
TestClasses = new ObservableCollection<TestClass>(testClasses);
另外,文本的类型是 string 而不是 int 。
更新:
我认为你的方式是明智的(不是黑客方式)。你只需要设置
<Button Text="Do Something" IsVisible="{Binding , Converter={StaticResource NullBooleanConverter}}" />
否则,您也可以创建Button的子类并定义两个BindableProperties,然后将它们绑定到Prop1和Prop2。它会很复杂,我不建议你选择它。
推荐阅读
- git - Git凭据捕获问题
- magento2 - M2 创建可配置产品并分配到类别但不在前端显示产品
- javascript - 使用 await 函数循环引发错误
- c# - 设置构造函数注入时出现 System.InvalidOperationException
- plone - 在卸载加载项时重置配置文件版本
- javascript - HTML 表单无响应
- java - Java Web 服务客户端给出 JaxWsClientProxy.invoke 错误
- python-3.x - 是否可以在 python 中同时写入多个套接字连接?
- java - 如何从字符串中读取哈希图
- mongodb - MongoDB分片