C# 使用BindableObject和绑定属性实现IValueConverter始终是默认值

C# 使用BindableObject和绑定属性实现IValueConverter始终是默认值,c#,xaml,xamarin,xamarin.forms,C#,Xaml,Xamarin,Xamarin.forms,我正在试图找到一种方法来处理CommandParameter不能与IValueConverter绑定的事实。通过阅读,我发现了一个建议,即在实现IValueConverter时继承BindableObject public class Number1Number2Converter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureIn

我正在试图找到一种方法来处理
CommandParameter
不能与
IValueConverter
绑定的事实。通过阅读,我发现了一个建议,即在实现
IValueConverter
时继承
BindableObject

public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}
尝试访问该属性时,该属性始终为0,可能采用默认值

public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}
作为参考,我使用Xamarin.FormsShell模板作为示例来简化问题:

public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}
使项目使用移动应用程序(Xamarin.Forms)时,请在创建项目时选择Shell。从那里我做了少量的修改。请注意,我只是设置一个断点来查看分配给
BindableProperty
的内容,该属性始终为0

public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}

public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}
本例向已提供的
Item.cs
类添加了两个属性

public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}
公共类项目{
公共字符串Id{get;set;}
公共字符串文本{get;set;}
公共字符串说明{get;set;}
//添加了这两个属性。其思想是将Number1绑定到标签的Text属性,并将Number2传递给该属性
公共整数1{get;set;}
公共整数2{get;set;}
}
MockDataStore.cs
的构造函数中,我为
Number1
Number2
属性添加了值

public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}
var mockItems=新列表{
新项{Id=Guid.NewGuid().ToString(),Text=“第一项”,Description=“这是项说明。”,Number1=5,Number2=20},
新项目{Id=Guid.NewGuid().ToString(),Text=“第二个项目”,Description=“这是项目说明。”,Number1=2,Number2=8},
新项{Id=Guid.NewGuid().ToString(),Text=“第三项”,Description=“这是项说明。”,Number1=3,Number2=6},
新项{Id=Guid.NewGuid().ToString(),Text=“第四项”,Description=“这是项说明。”,Number1=4,Number2=7},
新项{Id=Guid.NewGuid().ToString(),Text=“第五项”,Description=“这是项说明。”,Number1=1,Number2=10},
新项目{Id=Guid.NewGuid().ToString(),Text=“第六个项目”,Description=“这是项目说明。”,Number1=8,Number2=2}
};
具有BindableObject和IValueConverter的转换器

public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}
公共类Number1Number2Converter:BindableObject,IValueConverter{
公共静态只读BindableProperty ValueProperty=
Create(nameof(Value)、typeof(int)、typeof(Number1Number2Converter)、null);
公共整数值{
得到{
return(int)GetValue(ValueProperty);
}
设置{
设置值(ValueProperty,value);
}
}
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性){
//对象值确实指定了一个值,这是好的,但是值的绑定属性没有。应该传入Number2。
var testing123=价值;
返回null;
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性){
返回null;
}
}
在带有
var testing123=值的行上我放置了一个断点。我还没有尝试使用
,我只想看到它不是0。我在MockDataStore中分配给Number2的值中没有一个是0

public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}
下面是修改后的
ItemsPage.xaml
。请注意编号为1的标签,当然还有转换器

public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}

第一项
第二项
第三项
第四项
第五项
第六项

在本例中,
值始终为0。参数
对象值
被指定为Number1的int值,但
的可绑定属性应被指定为Number2。这个概念从根本上说是有缺陷的,还是我在正确的轨道上,但在实现某些东西时失败了?

您可以尝试将整个Item对象发送到转换器:

<Label Text="{Binding Path=., Converter={StaticResource Number1Number2Converter}}" />
public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}

我尝试了同样的方法,通过将绑定源设置为
DataTemplate
中的父元素,使其正常工作。为StackLayout命名并设置
值的绑定源和路径
属性

public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}
        <DataTemplate>
                <StackLayout x:Name="ItemLayout">
                    <Label>
                        <Label.Text>
                            <Binding Path="Number1">
                                <Binding.Converter>
                                    <converters:Number1Number2Converter Value="{Binding Path=BindingContext.Number2, Source={x:Reference ItemLayout}}" />
                                </Binding.Converter>
                            </Binding>
                        </Label.Text>
                    </Label>
                </StackLayout>
        </DataTemplate>


转换器的可绑定属性值已设置,可用于计算这两个数字。

老实说,最好的方法实际上是不尝试对命令参数进行数据绑定。如果您的目标只是操纵ViewModel中已经存在的两个数字,为什么不向ViewModel添加一个属性,该属性可以执行您试图在转换器中添加的操作?然后在Number1或Number2属性更改时对此属性调用RaisePropertyChanged?这种情况下的问题是项目模型本身需要额外的属性,而不是ViewModel。那里
public class Number1Number2Converter : IValueConverter {    
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value is Item item)
        {
             var number1 = item.Number1;
             var number2 = item.Number2,
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return null;
    }
}