1

I'm building a custom UserControl in WPF, which has a ViewModel associated. I also want do dynamically make controls in the code behind. But now I'm having problems binding the generated controls with the ViewModel properties. My code is:

<UserControl x:Class="SVT.Teste.UserControl1"
             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" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             DataContext="UserControl1ViewModel">
    <Grid Name="GridContainer">
    </Grid>
</UserControl>

and code behind:

    public UserControl1()
    {
        InitializeComponent();
        System.Windows.Controls.Button newBtn = new Button();
        newBtn.SetBinding(Button.ContentProperty, new Binding("Test"));
        GridContainer.Children.Add(newBtn);
    }

    public class UserControl1ViewModel
    {
        private string test = "ola";

        public string Test
        {
            get { return test; }
        }
    }

When I run this I get:

"System.Windows.Data Error: 40 : BindingExpression path error: 'Test' property not found on 'object' ''String' (HashCode=-946585093)'. BindingExpression:Path=Test; DataItem='String' (HashCode=-946585093); target element is 'Button' (Name=''); target property is 'Content' (type 'Object')"

Can you help me?

4 Answers 4

2

You are setting DataContext property of UserControl1 to a string instead of your view model instance.

You need to do something like this:

<UserControl xmlns:local="clr-namespace:NAMESPACE_WHERE_VIEWMODEL_IS_DEFINED">
    <UserControl.DataContext>
        <local:UserControl1ViewModel />
    </UserControl.DataContext>
    <!-- unrelated code omitted -->
</UserControl>
Sign up to request clarification or add additional context in comments.

1 Comment

Although all the answers works, this is the correct answer to me because and I have a View first approach and I dislike setting the databinding in the code behind. Thank you very much!
2

You are setting you DataContext to the type, not an instance that has the properties. In your method that creates the user control do :

          public UserControl1()
        {
            InitializeComponent();
            System.Windows.Controls.Button newBtn = new Button();
            newBtn.SetBinding(Button.ContentProperty, new Binding("Test"));
            GridContainer.Children.Add(newBtn);
            **DataContext = new UserControl1ViewModel();**
        }

You still have more work to do. The way you have it no notifications or update will happen. Implement the INotifyPropertyChanged interface (on UserControlViewModel). And remove setting DataContext in the XAML to the type.

Comments

1

try with this binding

Binding MyBinding = new Binding();
MyBinding.Path = new PropertyPath("Test");
newBtn.DataContext = new UserControl1ViewModel(); //or MyBinding.Source = new //UserControl1ViewModel();


newBtn.SetBinding(Button.ContentProperty, MyBinding);

Comments

0

max is right, but i have another question. why do you want create your usercontrol dynamic when you have a viemwodel you wanna bind to? makes no sense to me. let me explain:

if you have a viewmodel - you know in mind how this viewmodel should be rendered and what the bindings are. so you could create a usercontrol/view for this viewmodel

MyUserControl1View.xaml

<UserControl>
 <Grid>
   <Button Content="{Binding Test}"/>
   <!-- more controls and binding if the viewmodel expose more-->
 </Grid>
</UserControl>

so what you have now is a representation of your viewmodel. they are not connnected but your viewmodel should look like this and the binding are set. till now no datacontext is set at all.

all you have to do now is to go the viewmodel first approach and the use of datatemplates.

let us assume the following in your mainwindow

<Window>
 <Window.Resources>
  <DataTemplate Datatype="{x:Type local:Usercontrol1viewmodel}">
    <view:MyUserControl1View/>
  </DataTemplate>
 </Window.Resources>

now wpf knows how to render Usercontrol1viewmodel.

one step more in your mainwindow viewmodel you handle your Usercontrol1viewmodel.

 public Usercontrol1viewmodel MyWhatEver {get;set;} 

if you bind this property to a contentpresenter, you will see the wpf magic;)

 <ContentPresenter Content="{Binding MyWhatEver}"/>

now you see the MyUserControl1View in the contentpresenter, no dynamic view code needed. just go with your viewmodels.

ps: feel free to edit my bad english.

3 Comments

In my question I just explained a simple example. The thing is, I have a list of items that have a list of fields. This list of fields is dynamic. I iterate the list of fields, for each one I create a combobox or a textblock and bind it to the ViewModel - I'm still thinking how to do this last part. Thanks for your preoccupation ;)
np, when you write fields are dynamic - do you really mean the objects(viewmodel with Properties) are not defined at designtime? as long you have a defined type you can easy go with my aproach. i have to say i really dont like the "view first" approach when doing MVVM(except for application root/mainwindow)
I've elaborated my problem as a question itself (as the problem is from a design point of view rather than implementation as this one) here: stackoverflow.com/questions/11358669/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.