11 Replies - 1346 Views - Last Post: 13 September 2011 - 06:25 AM Rate Topic: -----

#1 Robin19  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 272
  • View blog
  • Posts: 552
  • Joined: 07-July 10

Databind Custom Object to Custom Control

Posted 06 September 2011 - 11:04 AM

I know there is something easy I'm missing. I've been working on this for several days but can't get it to show like it should. I hope someone can see how I've linked it up incorrectly. I've tried to edit out code that is not important.

I have an object called Pallet.
Spoiler


I create a Pallet object on one control and create an event. The event args contains that pallet object. The catching class adds that pallet to PackMixedViewControl. I debugged and verified that the Pallet is the same when this block of code runs.
Spoiler


The PackMixedViewControl databinds to an ObservableCollection of pallets. In a listbox, each pallet is assigned to an EditPalletControl.

EditPalletControl
Spoiler

PackMixedViewControl
Spoiler


By the time the EditPalletControl displays, all of the Pallet properties contains empty strings. Why is it creating a new empty pallet instead of using the pallet I passed it? Does anyone know where I went wrong? I'm to the point of manually controlling the databinding process.

Is This A Good Question/Topic? 0
  • +

Replies To: Databind Custom Object to Custom Control

#2 eclipsed4utoo  Icon User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1526
  • View blog
  • Posts: 5,961
  • Joined: 21-March 08

Re: Databind Custom Object to Custom Control

Posted 06 September 2011 - 11:34 AM

I don't see where you are binding anything to the ListBox. I haven't used MVVM all that much, but I see that you have your ViewModel as a resource, but you aren't binding anything to the ListBox.

Try this...

<UserControl.DataContext>
    <vm:CombinePalletsViewModel />
</UserControl.DataContext>
<Grid>

    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="9*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
	
    <ListView 
		ItemsSource="{Binding Pallets}"
		Grid.Row="1" 
		Margin="20" 
		Name="lstBxPallets" 
		Background="White" 
		HorizontalContentAlignment="Stretch" 
		VerticalContentAlignment="Stretch" 
		MaxHeight="700" >
		
        <me:EditPalletControl Pallet="{Binding Path=Self}" />
		
    </ListView>
</Grid>



Though I am not sure this is going to work because I added binding to the Pallets property, but that property doesn't seem to be part of the ViewModel(you didn't show your ViewModel).

If you are setting the DataContext of the control to your ViewModel, you should be binding to properties on the ViewModel.

Was there a specific reason you created two custom controls instead of just using a new style for a ListBoxItem?
Was This Post Helpful? 2
  • +
  • -

#3 ragingben  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 175
  • View blog
  • Posts: 641
  • Joined: 07-October 08

Re: Databind Custom Object to Custom Control

Posted 07 September 2011 - 02:36 AM

Also, if you think you will need to bind to and from properties of Pallet, you will need to implement INotifyPropertyChanged
Was This Post Helpful? 2
  • +
  • -

#4 Robin19  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 272
  • View blog
  • Posts: 552
  • Joined: 07-July 10

Re: Databind Custom Object to Custom Control

Posted 07 September 2011 - 09:28 AM

I created two custom controls for OOP reasoning. The EditPalletControl is used (statically instanced and created through code) three other places. It will eventually be used about ten more times throughout the project. Practicing OOP, I only wanted to create the XAML once. The PalletMixedViewControl is a "page" that sits inside a module "page" that resides inside the main control window. It sounds confusing, but it makes sense for this project. The main window only worries about moving between modules. The modules are sometimes only one page. Some modules (like PalletMixedControl) show static information and has a subwindow that changes based on user choices.

I forgot to add the ViewModel. It is simple. Did I mess up there?
    public class CombinePalletsViewModel
    {
        private ObservableCollection<Pallet> _pallets = new ObservableCollection<Pallet>();
        public ObservableCollection<Pallet> Pallets
        {
            get { return _pallets; }
        }
    }


I made many edits and eventually gave up on tying everything together through dependency. I'm the only real programmer here. The others are all networking people who've moved on from scripting enough to be dangerous. I'm known as the best practices nazi because I am the only one that tries to create objects, reuse code, refuses to use "GOTO", etc. I'm also the only one that is working on this project. I subscribed to the _palletView.Pallets.Collectionchanged event and have this code.
        private void PalletsChanged()
        {
            lstBxPallets.Items.Clear();
            foreach (Pallet p in _palletView.Pallets)
            {
                EditPalletControl epc = new EditPalletControl();
                epc.Pallet = p;
                epc.Exitable = true;
                epc.EditClick += Edit_Pallet_Click;
                epc.ExitClick += ExitPalletControl_ExitClick;
                lstBxPallets.Items.Add(epc);
            }
            UpdateCount(); // calculates and sets the count label on the page
        }

This post has been edited by Robin19: 07 September 2011 - 09:29 AM

Was This Post Helpful? 0
  • +
  • -

#5 eclipsed4utoo  Icon User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1526
  • View blog
  • Posts: 5,961
  • Joined: 21-March 08

Re: Databind Custom Object to Custom Control

Posted 07 September 2011 - 12:18 PM

That last piece of code shouldn't be needed. The ObservableCollection is a collection that implements the INotifyPropertyChanged interface, which will notify the UIElement that it's bound to that it's collection has changed. So you really don't need to clear the ListBox and re-add all of the controls again. It *should* do it on it's own.
Was This Post Helpful? 0
  • +
  • -

#6 Robin19  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 272
  • View blog
  • Posts: 552
  • Joined: 07-July 10

Re: Databind Custom Object to Custom Control

Posted 07 September 2011 - 12:41 PM

Except that it creates a new Pallet for each EditPalletControl instead of using the Pallets in the list. I have put breakpoints to prove that public Pallet() gets called even though there is a Pallet (with info) already in the Collection. That is why the EditPalletControl isn't showing information. It is being passed a pallet with no information instead of a pallet from the collection.
Was This Post Helpful? 0
  • +
  • -

#7 eclipsed4utoo  Icon User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1526
  • View blog
  • Posts: 5,961
  • Joined: 21-March 08

Re: Databind Custom Object to Custom Control

Posted 08 September 2011 - 05:17 AM

Looking at your original post, looks like you are adding the new incoming pallet to the PackMixedViewControl. However, you seem to be binding the Pallet collection from the ViewModel to the ListBox. If this is true, that would be your problem. You should be adding the new Pallet to the ViewModel, not the PackMixedViewControl.

This is the code I am referring to.

void pmac_PalletReturned(object sender, PalletInfoEventArgs e)
{
    // view is the PackMixedViewControl
    view.Pallets.Add(e.Pallet);
    // displays the PackMixedViewControl
    NavigateView();
}



Looks like you are adding the pallet to the PackMixedViewControl. This kind of defeats the purpose of the ViewModel having a collection for the Pallets AND the control having a collection for the Pallets.

Personally, I would remove the collection from the control, and only use the collection from the ViewModel. This way, you can use the DataContext that you have set to the ViewModel.
Was This Post Helpful? 1
  • +
  • -

#8 Robin19  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 272
  • View blog
  • Posts: 552
  • Joined: 07-July 10

Re: Databind Custom Object to Custom Control

Posted 09 September 2011 - 09:14 AM

I did use the collection from the VM. Pallets is a public face to the VM's collection. Or do I need to expose the VM itself?

PackMixedViewControl:
CombinePalletsViewModel _palletView;
public ObservableCollection<Pallet> Pallets
{
    get { return _palletView.Pallets; }
    set { _palletView.Pallets = value; } // this has been deleted.  Only get needed.
}

Was This Post Helpful? 0
  • +
  • -

#9 eclipsed4utoo  Icon User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1526
  • View blog
  • Posts: 5,961
  • Joined: 21-March 08

Re: Databind Custom Object to Custom Control

Posted 09 September 2011 - 01:00 PM

There is really no need for the property to be in both places. It's already in the ViewModel, so if you need to add/remove from the collection, you do that through the ViewModel directly.

When binding, you already have the ViewModel as the DataContext, it should be used.

I will see if I can do a sample similar to what you are doing(custom control as an ItemTemplate for a Listbox while using MVVM).
Was This Post Helpful? 0
  • +
  • -

#10 eclipsed4utoo  Icon User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1526
  • View blog
  • Posts: 5,961
  • Joined: 21-March 08

Re: Databind Custom Object to Custom Control

Posted 10 September 2011 - 06:59 AM

Alright, let's see how this works out for you. I did a sample project using MVVM, with a ListBox that had a custom user control as the ListBox's item template. I will post all of the code.

So first is the model...Person
public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}



Next is the ViewModel... PersonViewModel
Spoiler


So the ViewModel will handle adding a person to our collection of People. When that addition is made, we fire the PropertyChanged event(from the INotifyPropertyChanged interface) to let any controls that are binding to the collection that it has been changed.

Next is the custom control for the ListBox Item template... PersonEditControl
(there is no code in the code behind)
Spoiler


As you can see, I am binding to the FirstName, LastName, and Age properties of the Person class. This control's DataContext will be a Person object, so that's why we bind to those properties.

Last is the MainWindow page that has the ListBox and a button.

XAML
Spoiler


So for the main window, we have set our DataContext of the window to our PersonViewModel. The ListBox has it's ItemsSource property bound to the People collection of the ViewModel. The ListBox's item template will be bound to the individual object type in the collection(Person object).

Code
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void AddPersonButton_Click(object sender, RoutedEventArgs e)
    {
        MyPersonViewModel.AddPerson();
    }
}



That's really all of the code. Simply clicking the Add Button will add a new person to our collection in the ViewModel, and the ListBox will be updated to show the new addition. And since we have set the item template, it will be displayed with the PersonEditControl.

Let me know if you have any questions. I know it's not exactly like what you are doing, but it should help.

I have attached the VS2010 project so you can look at it and run it to see how it works. If you need it in VS2008, just let me know.

Attached File  MVVMExample.zip (71.41K)
Number of downloads: 65
Was This Post Helpful? 1
  • +
  • -

#11 Robin19  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 272
  • View blog
  • Posts: 552
  • Joined: 07-July 10

Re: Databind Custom Object to Custom Control

Posted 13 September 2011 - 06:21 AM

I've got it working now. I don't know what was wrong in the first place, and so much has changed that I'll never know what I did wrong. Thank you eclipsed (and ragingben about the INotifyPropertyChanged). I made sure +1's were passed around. WPF is like a ship in a bottle. It's a pain in the butt to set up and can be frustrating as hell, but when it is running right it is a beautiful thing to look at.
Was This Post Helpful? 0
  • +
  • -

#12 eclipsed4utoo  Icon User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1526
  • View blog
  • Posts: 5,961
  • Joined: 21-March 08

Re: Databind Custom Object to Custom Control

Posted 13 September 2011 - 06:25 AM

Once I started learning MVVM with WPF, WOW...it's just amazingly powerful, though a pain-in-the-ass to setup.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1