问题
If you know what attached property is, then imagine a case where you need to supply 2 or more of them altogether (here is an example) and only if all of them are set something will happens.
This sounds like calling a method with parameters to me, therefore a tittle.
Does anyone tried anything like this? I'd imagine it can also solve my current issue with such ugly looking workaround (having 10x times of 3 property):
<TextBox local:DynamicBinding.Property1="{Binding IsCheckedPath}"
local:DynamicBinding.Source1="{Binding IsCheckedSource}"
local:DynamicBinding.Target1="IsChecked"
local:DynamicBinding.Property2="{Binding WidthPath}"
local:DynamicBinding.Source2="{Binding WidthSource}"
local:DynamicBinding.Target2="Width"
local:DynamicBinding.Property3="{Binding TextPath"
local:DynamicBinding.Source3="{Binding TextSource}"
local:DynamicBinding.Target3="Text" ... />
Ideally I'd like something like this
<TextBox IsChecked="{Binding Path={Binding IsCheckedPath}, Source={Binding IsCheckedSource}}"
Width="{Binding Path={Binding WidthPath}, Source={Binding WidthSource}}"
Text="{Binding Path={Binding TextPath}, Source={Binding TextSource}}"
Or maybe even more brief, any ideas?
回答1:
Ok, so instead of your ideal binding
Text="{Binding Path={Binding MyText}, Source={Binding MySource}}"
I'd suggest to use a switch property
Text="{Binding BindingMyText}"
that could be implemented with a ViewModel visitor (it looks more complicated but it's done on purpose to make illegal states unrepresentable)
internal abstract class IPropVisitor<A>
{
internal abstract A bindingMyText(ModelA source);
internal abstract void bindingMyText(ModelA source, A val);
internal abstract A bindingMyText(ModelB source);
internal abstract void bindingMyText(ModelB source, A val);
}
internal class ViewModelVisitor : IPropVisitor<string>, INotifyPropertyChanged
{
internal ViewModelVisitor(ModelSource model)
{
modelSource = model;
BindingMyText = "Test!";
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
override internal string bindingMyText(ModelA source)
{
return source.MyTextA;
}
override internal void bindingMyText(ModelA source, string val)
{
source.MyTextA = val;
}
override internal string bindingMyText(ModelB source)
{
return source.MyTextB;
}
override internal void bindingMyText(ModelB source, string val)
{
source.MyTextB = val;
}
private ModelSource modelSource;
public ModelSource ModelSource
{
get { return modelSource; }
set
{
modelSource = value;
OnPropertyChanged("ModelSource");
OnPropertyChanged("BindingMyText");
}
}
public string BindingMyText
{
get
{
return modelSource.accept(this);
}
set
{
modelSource.accept(this, value);
OnPropertyChanged("BindingMyText");
}
}
}
and many different model sources
public abstract class ModelSource : ViewModelBase
{
abstract internal A accept<A>(IPropVisitor<A> visitor);
abstract internal void accept<A>(IPropVisitor<A> visitor, A val);
}
class ModelA : ModelSource
{
private string myTextA;
public string MyTextA
{
get { return myTextA; }
set {
myTextA = value;
OnPropertyChanged("MyTextA");
}
}
internal override A accept<A>(IPropVisitor<A> visitor)
{
return visitor.bindingMyText(this);
}
internal override void accept<A>(IPropVisitor<A> visitor, A val)
{
visitor.bindingMyText(this, val);
}
}
class ModelB : ModelSource
{
private string myTextB;
public string MyTextB
{
get { return myTextB; }
set
{
myTextB = value;
OnPropertyChanged("MyTextB");
}
}
internal override A accept<A>(IPropVisitor<A> visitor)
{
return visitor.bindingMyText(this);
}
internal override void accept<A>(IPropVisitor<A> visitor, A val)
{
visitor.bindingMyText(this, val);
}
}
Please note that this is simply the basic idea, so it is really an initial draft and it is not intended to automatically fit any specific context...
来源:https://stackoverflow.com/questions/42065442/attached-method-with-parameters