我尝试在输入绑定属性嵌套字段时启用有界的按钮,但即使所有属性都填充了数据,该按钮也会被禁用。 我应该改变什么?
这是我的基本视觉状态
public class BaseVisualState : Exrin.Framework.VisualState
{
public BaseVisualState() : this(null)
{
}
public BaseVisualState(IBaseModel i_Model) : base(i_Model)
{
PropertyObservable = Observable.FromEventPattern(
(EventHandler<PropertyChangedEventArgs> i_Event) => new PropertyChangedEventHandler(i_Event),
i_EventChanged => this.PropertyChanged += i_EventChanged,
i_EventChanged => this.PropertyChanged -= i_EventChanged);
}
public IObservable<EventPattern<PropertyChangedEventArgs>> PropertyObservable { get; private set; }
}
我的视觉状态是
public class BeaconAddVisualState : BaseVisualState
{
private readonly IBeaconAddModel r_Model;
public BeaconAddVisualState(IBeaconAddModel i_Model)
: base(i_Model)
{
r_Model = i_Model;
}
[Binding(BindingType.TwoWay)]
public Beacon Beacon
{
get
{
return Get<Beacon>();
}
set
{
Set(value);
}
}
public override async void Init()
{
Beacon = new Beacon();
}
}
信标类通知属性已更改
public class Beacon : Document<Guid>, INotifyPropertyChanged
{
private string m_ProximityUuid;
private int? m_Major;
private int? m_Minor;
[Required]
public string ProximityUuid
{
get
{
return m_ProximityUuid;
}
set
{
if(m_ProximityUuid != value)
{
m_ProximityUuid = value;
notifyPropertyChanged();
}
}
}
[Required]
public int? Major
{
get
{
return m_Major;
}
set
{
if (m_Major != value)
{
m_Major = value;
notifyPropertyChanged();
}
}
}
[Required]
public int? Minor
{
get
{
return m_Minor;
}
set
{
if (m_Minor != value)
{
m_Minor = value;
notifyPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
// This method is called by the Set accessor of each property.
// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void notifyPropertyChanged([CallerMemberName] string i_PropertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(i_PropertyName));
}
}
}
这是viewmodel
public class BeaconAddViewModel : BaseAuthViewModel
{
private readonly IBeaconAddModel r_Model;
private readonly IDisposable r_Subscription;
public BeaconAddViewModel(IBeaconAddModel i_Model)
: base(new BeaconAddVisualState(i_Model))
{
r_Model = i_Model;
r_Subscription = State.PropertyObservable.Where(
i_Arg => i_Arg.EventArgs.PropertyName == nameof(State.Beacon.ProximityUuid)
|| i_Arg.EventArgs.PropertyName == nameof(State.Beacon.Major) || i_Arg.EventArgs.PropertyName == nameof(State.Beacon.Minor)).Subscribe(
i_Arg =>
{
AddCommand.OnCanExecuteChanged();
});
}
private BeaconAddVisualState State => VisualState as BeaconAddVisualState;
public override Task OnNavigated(object i_Args)
{
return base.OnNavigated(i_Args);
}
public IRelayCommand AddCommand
{
get
{
return GetCommand(
() =>
{
return new RelayCommand(
async (i_Parameter) =>
{
await r_Model.AddBeacon(i_Parameter as Beacon);
await NavigationService.Navigate("Beacons");
}, (i_Obj) => !string.IsNullOrEmpty(State.Beacon.ProximityUuid) && State.Beacon.Major.HasValue && State.Beacon.Minor.HasValue;
});
}
}
public override void Disposing()
{
base.Disposing();
r_Subscription?.Dispose();
}
}
答案 0 :(得分:0)
这里的问题是你在Beacon类中触发INPC,但是BaseVisualState只是在看Beacon(对象本身)是否在改变。
因此,你必须将Beacon之外的属性直接带入VisualState,或者转发INPC事件。
e.g。在你的灯塔集中
var beacon = value;
Set(value);
value.OnPropertyChanged += (s,e) => { OnPropertyChanged(nameof(Beacon)); }
这意味着,每次更改Beacon中的任何属性时,都会说Beacon类本身已更改,并触发VisualState的INPC。
注意:确保事件在重置时处理掉。这意味着不会像上面所示那样在anon函数中执行它,而是执行+ =并将其选中以创建另一种方法。
答案 1 :(得分:0)
感谢亚当的帮助。 这就是id到底做了什么,也许它可以帮助别人
public class BeaconAddVisualState : BaseVisualState
{
private readonly IBeaconAddModel r_Model;
private Beacon m_Beacon;
public BeaconAddVisualState(IBeaconAddModel i_Model)
: base(i_Model)
{
r_Model = i_Model;
}
[Binding(BindingType.TwoWay)]
public Beacon Beacon
{
get
{
return m_Beacon;
}
set
{
if(m_Beacon != value)
{
if(m_Beacon != null)
{
m_Beacon.PropertyChanged -= m_Beacon_PropertyChanged;
}
m_Beacon = value;
m_Beacon.PropertyChanged += m_Beacon_PropertyChanged;
OnPropertyChanged();
}
}
}
public override async void Init()
{
Beacon = new Beacon();
}
public override void Disposing()
{
if (m_Beacon != null)
{
m_Beacon.PropertyChanged -= m_Beacon_PropertyChanged;
}
base.Disposing();
}
private void m_Beacon_PropertyChanged(
object i_Sender,
System.ComponentModel.PropertyChangedEventArgs i_EventArgs)
{
OnPropertyChanged(nameof(Beacon));
}
}