Attached method with parameters

耗尽温柔 提交于 2020-01-06 21:52:42

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!