Xamarin.forms Xamarin集合基于同一Grid.Row中的多个绑定属性显示网格内的按钮,而不编辑原始模型

Xamarin.forms Xamarin集合基于同一Grid.Row中的多个绑定属性显示网格内的按钮,而不编辑原始模型,xamarin.forms,Xamarin.forms,我有一个按钮,可以出现在网格的每一行中。 如果“行”中的任何绑定属性为空,我需要隐藏该按钮。 这是使用MVVM模式,以便ViewModel具有ObservableCollection 非常简单的示例: public class TestClass { public int? Prop1 { get; set; } public int? Prop2 { get; set; } } public class TestViewModel { private Observab

我有一个按钮,可以出现在网格的每一行中。
如果“行”中的任何绑定属性为空,我需要隐藏该按钮。
这是使用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();
    }
}

还可以将属性IsVisible绑定到ViewModel

<StackLayout Grid.Column="2">
   <Button Text="Do Something" 
           IsVisible="{Binding isVisible}" />
</StackLayout>
和在ViewModel中

<StackLayout Grid.Column="2">
   <Button Text="Do Something" 
           IsVisible="{Binding isVisible}" />
</StackLayout>
var testClasses=newlist();
添加(新的TestClass(“1”,“1”));
添加(新的TestClass(null,“2”);
Add(新的TestClass(“1”,null));
TestClasses=新的ObservableCollection(TestClasses);
此外,文本的类型是string而不是int

更新:

我认为你的方式是明智的(不是一个黑客的方式)。你只需要设置

<Button Text="Do Something" IsVisible="{Binding , Converter={StaticResource NullBooleanConverter}}" />


否则,您还可以创建按钮的子类,并定义两个可绑定属性,然后将它们绑定到Prop1Prop2。这将很复杂,我不建议您选择它。

我同意编辑我的“模型”是实现这一点的一种方法,但我提供的示例过于简化。在我的工作环境中,模型位于Web、Windows、WPF和Xamarin项目之间共享的外部库中,不允许我编辑原始模型。我应该在标题/问题中说明这一点。我非常感谢你的帮助。这在WPF中可以通过使用IMultiValueConverter实现,但在Xamarin中找不到类似的方法。您可以在ViewModel中实现。请原谅我听起来很愚蠢,但我如何在ViewModel中实现这一点?我的TestClass是一个绑定到网格的集合,因此我不知道如何在不构建扩展当前TestClass的另一个模型的情况下实现这一点。我确实找到了一种“黑客”的方法,我将在上面列出,但如果你有其他方法,我真的很想学习这种方法。构建另一个扩展当前TestClass的模型是一种好方法。为什么不这样做呢?我试图不扩展这些模型,因为这些模型是poco传递给OData服务的,我们正在努力使它们尽可能干净。基本上,我们从OData服务中拖出一个json对象,对其进行编辑,然后将其发回服务。如果模型与服务上的模型不匹配,那么服务将拒绝json。我猜我们可以创建本地模型,然后使用映射器,但仅仅根据模型中的两个字段在按钮上设置“可见”似乎有些过分。
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;
      }
  }

}
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);
<Button Text="Do Something" IsVisible="{Binding , Converter={StaticResource NullBooleanConverter}}" />