Levi Fuller
Levi Fuller

Reputation: 15631

How to bind to an entire UI Element?

I have a custom control which contains a WebView. I also have a ViewModel which takes in a WebView in the constructor and modifies it. It passes the WebView control to the VM where it is modified.

Originally, I wanted to do this:

    public static readonly DependencyProperty AccountProperty =
       DependencyProperty.Register("Account", typeof(Account), typeof(AccountViewControl),
           new PropertyMetadata(null));
    public Account Account {
        get { return (Account)GetValue(AccountProperty); }
        set {
            SetValue(AccountProperty, value);
            SiteViewModel SiteVM = new SiteViewModel(wv: wvAccount);
            SiteVM.CurrentAccount = value;
            SiteVM.LoginToSite();
        }
    }

Each control has a WebView named wvAccount which would be passed into the SiteViewModel constructor. However, since the setter is bypassed when using a DependencyProperty, I have to use a static PropertyChanged event to call SiteVM.LoginToSite which won't have access to the WebView within the control's XAML.

My first thought was to add a WebView property to the SiteVM and bind the UI's WebView to that element, however, I can't seem to find any way to bind to an entire UI element.

Here's what I want to achieve:

public static readonly DependencyProperty SiteViewModelProperty =
    DependencyProperty.Register("Account", typeof(SiteViewModel), typeof(AccountViewControl),
        new PropertyMetadata(null, OnSiteViewModelChanged));

private static void OnSiteViewModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
    SiteViewModel siteVM = (SiteViewModel)e.NewValue;
    siteVM.LoginToSite();
}

And I would bind it like so:

<WebView {x:Bind=SiteVM.WebView} Visibility="{Binding ShowEditControl, ElementName=accountControl, Converter={ThemeResource InverseVisConverter}}" x:Name="wvAccount" />

Is there perhaps a way (or better way) to achieve this?

Upvotes: 0

Views: 112

Answers (1)

Jerry Nixon
Jerry Nixon

Reputation: 31803

Generally, I think most developers would agree that this is a bad idea. That doesn't mean you can't do it, though. Let's pretend your element is named MyElement. Do this:

<Page.DataContext>
    <local:MyViewModel Element="{Binding, ElementName=MyElement}" />
</Page.DataContext>

Just remember that the Element property you create in your ViewModel is of type UIElement or the actual element type if you want it to be more strongly-typed.

Best of luck!

Upvotes: 2

Related Questions