Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

WPF – MVVM binding in UserControl

I’m testing a sample binding in MVVM pattern. I’m using package GalaSoft.MvvmLight. Binding from MainViewModel to MainWindow is normal but I can’t binding data from a ViewModel (ImageViewModel) to View (ImageView). All my code is below

in App.xaml

<Application x:Class="WpfApplication1.App"         
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr- 
namespace:WpfApplication1" StartupUri="MainWindow.xaml" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d1p1:Ignorable="d" 
xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Application.Resources>
<ResourceDictionary>
  <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr- 
  namespace:WpfApplication1.ViewModel" />
</ResourceDictionary>
</Application.Resources>
</Application>

in MainWindow.xaml

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:v="clr-namespace:WpfApplication1.View"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApplication1"
    DataContext="{Binding Main, Source={StaticResource Locator}}"
    mc:Ignorable="d"
    Title="MainWindow" Height="800" Width="1000">
<Grid>
    <Grid Grid.Column="1">
        <v:ImageView DataContext="{Binding ImageVM}"/>
    </Grid>
       
</Grid>

in ImageView.xaml

<UserControl x:Class="WpfApplication1.View.ImageView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:WpfApplication1.View"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300"
         Name="ucImage">

<UserControl.DataContext>
    <Binding Path="Main.ImageVM" Source="{StaticResource Locator}"/>
</UserControl.DataContext>

<Grid>
    <TextBox x:Name="label" Text="{Binding TestText, ElementName=ucImage}" Width="100" 
     Height="50"/>
</Grid>
</UserControl>

in ViewModelLocator.cs

using GalaSoft.MvvmLight;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApplication1.ViewModel
{
public class ImageViewModel: ViewModelBase
{
    public string _TestText;
    public string TestText
    {
        get
        {
            return _TestText;
        }
        set
        {
            _TestText = value;
            RaisePropertyChanged(() => this.TestText);
        }
    }


    public ImageViewModel()
    {
        TestText = "asdasdasdasdas";
    }
}
}

in MainViewModel

public class MainViewModel : ViewModelBase
{
    private ImageViewModel _ImageVM;
    public ImageViewModel ImageVM
    {
        get { return _ImageVM; }
        set { Set(ref _ImageVM, value); }
    }


    public MainViewModel()
    {
        ImageVM = new ImageViewModel();
    }
}

in ImageViewModel.cs

using GalaSoft.MvvmLight;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApplication1.ViewModel
{
public class ImageViewModel: ViewModelBase
{
    public string _TestText;
    public string TestText
    {
        get
        {
            return _TestText;
        }
        set
        {
            _TestText = value;
            RaisePropertyChanged(() => this.TestText);
        }
    }


    public ImageViewModel()
    {
        TestText = "asdasdasdasdas";
    }
}

}

This error from output is

System.Windows.Data Error: 40 : BindingExpression path error:
‘TestText’ property not found on ‘object’ ”ImageView’
(Name=’ucImage’)’. BindingExpression:Path=TestText;
DataItem=’ImageView’ (Name=’ucImage’); target element is ‘TextBox’
(Name=’label’); target property is ‘Text’ (type ‘String’)

Anyone who comes up with a solution would be greatly appreciated!

>Solution :

The expression

Text="{Binding TestText, ElementName=ucImage}"

expects a TestText property in the ImageView control, which apperently does not exists – that is what the error message says.

You would simply write the following to make the element in the control’s XAML bind directly to the view model object in its DataContext:

<TextBox Text="{Binding TestText}" .../>

In order to make the control independent of a specific view model, it should expose a bindable property, i.e. a dependency property like this:

public partial class ImageView : UserControl
{
    public ImageView()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register(
            nameof(Text), typeof(string), typeof(ImageView));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
}

which would work with

<TextBox Text="{Binding Text, ElementName=ucImage}"

in the control’s XAML and without explictly setting the control’s DataContext, i.e. without the <UserControl.DataContext> section in its XAML.

The property would be bound like

<v:ImageView DataContext="{Binding ImageVM}" Text="{Binding TestText}"/>

or just

<v:ImageView Text="{Binding ImageVM.TestText}"/>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading