xamarin 尝试将自定义控件属性绑定到IsEnabled属性,但有一个属性未更新

o8x7eapl  于 2023-10-14  发布在  其他
关注(0)|答案(1)|浏览(169)

我有一个自定义内置的数字输入,其中包括一个步进。一切都是完全功能性的,除了关于属性绑定的一件事。IsEnabled和Opacity属性绑定到增量/减量按钮。基本上,只要'Value'属性>然后Min或< Max,就可以点击递增或递减。
唯一一次它不按预期工作是当'Max'属性而不是'Value'被更新时。在某些情况下,我有对象集合,其中条目需要用作输入的一部分。
下面是与增量按钮相关的一些相关代码和属性。注意装订。我绑定到'值',但也比较'最大',它.但实际上,绑定仅在“Value”更改时触发。

public double? Value { get { return (double?)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } }
public static readonly BindableProperty ValueProperty = BindableProperty.Create(nameof(Value), typeof(double?), typeof(Nu), null);

public double? Max { get { return (double?)GetValue(MaxProperty); } set { SetValue(MaxProperty, value); } }
public static readonly BindableProperty MaxProperty = BindableProperty.Create(nameof(Max), typeof(double?), typeof(NumericEntry), null);

public event EventHandler Tapped;

new PancakeView (true, 0) // This is tappable, it increments 'Value' by one
{ 
   Content = new FontAwesome
   {
      Text = "\u002b", // Plus Symbol
   }.Bind(OpacityProperty, nameof(Value), source: this, convert: (double? d) => Max == null || (d.HasValue && d.Value < Max) ? 1 : .25)
   .CenterExpand()
}.Bind(IsEnabledProperty, nameof(Value), source: this, convert: (double? d) => Max == null || (d.HasValue && d.Value < Max))
.Invoke(pv => pv.TapEvent += Increment_Tapped)

private void Increment_Tapped(object s, EventArgs e)
{
   PancakeView pv = s as PancakeView;
   OnStepperPress(pv);

   if (Value == null)
   {
      Value = 0;
   }

   if (Value < Max || Max == null)
   {
      Value += 1;
   }

   OnSubmitTap(s, e);
}

private void OnSubmitTap(object sender, EventArgs e)
{
   Tapped?.Invoke(this, e);
}

**

必须在Bindable Property中的属性更改回调方法中触发PropertyChanged。看沈立群的回答,就搞定了。
感谢@Jason,他提供了相同的解决方案,但我现在意识到,当我实现它时,它不起作用的原因是因为我没有在添加到相关ObservableCollection的初始对象上示例化ValueMax

pu3pd22g

pu3pd22g1#

更新

如果有办法同时解雇麦克斯和超值
我完全同意你的看法。
BindableProperty可以是Detect property changes
因此,您可以为Max属性添加此属性更改回调方法。

public static readonly BindableProperty MaxProperty = BindableProperty.Create(nameof(Max), typeof(double?), typeof(NumericEntry), null,
        propertyChanged:OnMaxPropertyChanged);

    private static void OnMaxPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        NumericEntry ne = bindable as NumericEntry;
        ne.OnPropertyChanged(nameof(Value));
    }

Max属性更改时,Value属性更改也会触发。
忽略我的原始帖子。
让我们看看NumericEntry.cs中的代码:

Content = new FontAwesome
         {
         Text = "\uf068",
         }.Bind(OpacityProperty, nameof(Value)....

在此代码中,您将OpacityProperty绑定到ValueValue属性是在NumericEntry.cs中定义的BindableProperty。此Value属性绑定到 *Row类 * 中的Amount属性。

**每个NumericEntry绑定到RowCollection中对应的一行。**它们是独立的。

现在假设在为ID 2条目添加一个步骤时,只更改了ID 2条目的Value属性。ID 1和ID 3的Value属性不会更改。所以它们的OpacityProperty或IsEnabledProperty不会改变。

  • 解决办法 *

关键是当一个条目的某个属性发生变化时,它应该通知其他条目。我认为基于现有的代码结构很难做到这一点。所以我可以尝试不同的方式。
对于行类,我会
1.再添加两个属性来控制每个步进器的IsEnable,例如:

private bool isPlusEnabled;
public bool IsPlusEnabled { get => id; set => Set(ref isPlusEnabled, value); }

private bool isMinusEnabled;
public bool IsMinusEnabled { get => isMinusEnabled; set => Set(ref isMinusEnabled, value); }

2.在NumericEntry.cs中再添加两个BindableProperty

public bool IsPlusEnabled { get { return (bool)GetValue(IsPlusEnabledProperty); } set { SetValue(IsPlusEnabledProperty, value); } }

public static readonly BindableProperty IsPlusEnabledProperty = BindableProperty.Create(nameof(IsPlusEnabled), typeof(bool), typeof(NumericEntry) );

public bool IsMinusEnabled { get { return (bool)GetValue(IsMinusEnabledProperty); } set { SetValue(IsMinusEnabledProperty, value); } }
public static readonly BindableProperty IsMinusEnabledProperty = BindableProperty.Create(nameof(IsMinusEnabled), typeof(bool), typeof(NumericEntry) );

3.更改RowCollection_ItemPropertyChanged中的某些逻辑

private void RowCollection_ItemPropertyChanged(object sender, ItemPropertyChangedEventArgs e)
{

    foreach (Row r in RowCollection)
    {
        ...
        if(r.Amount < r.Max)
        {
            r.IsPlusEnabled = true;
        }
        else
        {
            r.IsPlusEnabled = false;
        }
        if(r.Amount > 0)
        {
            r.IsMinusEnabled = true;
        }
        else
        {
            r.IsMinusEnabled = false;
        }
        ....
    }

4.连接属性

.Bind(OpacityProperty, nameof(IsPlusEnabled), source: this, convert:boolToOpacity)
                                                                                     
.Bind(IsEnabledProperty, nameof(IsPlusEnabled), source: this)

希望能帮上忙!

相关问题