WPF ComboBox TwoWay binding with XML

Hi Experts,

I'm writing my first WPF form in VB.NET VS2012 (finally taking the leap to WPF) and have run into a problem.

I have a data file (XML)  that contains all the values for my comboboxes.

At run time, if the item the user needs is not in the list, I need them to be able to add it to the list and have it store in the xml file.

In the past I did that all programatically rather than using data binding, which I want to do now.

the line in the 3rd code block

cb.Items.Add(CustomInputBox.Text)

errors out with
"Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead."

And there is my problem, not sure how to add it to the source.....
I'm also not sure the binding to the ComboBox is correct either, though it DOES display all the elements in the XML file.


Here's the important bits of my XAML:

<UserControl x:Class="FireControl"
             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:WPFInputBox="clr-namespace:WPFInputBox;assembly=WPFInputBox"
             
             mc:Ignorable="d" Width="903" Height="842">
    <UserControl.Resources>
        <XmlDataProvider x:Key="Data" XPath="/Data" Source="pack://siteoforigin:,,,/Data/Data.xml"/>
    </UserControl.Resources>


    <Grid x:Name="MainGrid" HorizontalAlignment="Left" Height="842" VerticalAlignment="Top" Width="903">
        <Grid.Resources>
            <XmlDataProvider x:Key="Data" XPath="/Data" Source="pack://siteoforigin:,,,/Data/Data.xml"/>
        </Grid.Resources>
        
        <GroupBox Header="General Info" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="217" Width="238" FontWeight="Bold">
            <Grid>

                <Label Content="Type" HorizontalAlignment="Left" Margin="6,10,0,0" VerticalAlignment="Top" FontWeight="Normal"/>
                <ComboBox x:Name="Fire_Type" HorizontalAlignment="Left" Margin="96,10,0,0" VerticalAlignment="Top" Width="120" FontWeight="Normal"  ItemsSource="{Binding Source={StaticResource Data}, XPath=Type/Type, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" DisplayMemberPath="@id" />

'.....
</Grid>
</GroupBox>
<WPFInputBox:InputBox x:Name="CustomInputBox" Grid.ColumnSpan="2" Visibility="Collapsed" />
</Grid>
</UserControl>

Open in new window


XML Excerpt:
<Data>
  <Type>
    <Type id="[Add New Type]" />
    <Type id="Type 1" />
    <Type id="Type 2" />
    <Type id="Type 3" />
  </Type>
</Data>

Open in new window


Private Sub Fire_Type_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles Fire_Type.SelectionChanged

        Dim cb As ComboBox = DirectCast(sender, ComboBox)
        If cb.SelectedIndex = 0 Then
            ShowInputBox("Add New Type")
            If CustomInputBox.OK Then
                cb.Items.Add(CustomInputBox.Text) 
            End If
        End If
    End Sub

Open in new window

LVL 1
sgaggerjAsked:
Who is Participating?
 
AshokCommented:
You are doing this correctly in your post ID: 39731961.

You are supposed to add to XML directly.

You cannot add directly to ComboBox in this situation.

By the way, if you use ObservableCollection and add from XML to ObservableCollection, you would then add new item to ObservableCollection and it would refresh automatically.
0
 
sgaggerjAuthor Commented:
So I haven't been able to figure out two way databinding on the combo box, so I came up with the following:

I Changed the selection changed handler to

Private Sub Fire_Type_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles Fire_Type.SelectionChanged

        Dim cb As ComboBox = DirectCast(sender, ComboBox)
        If cb.SelectedIndex = 0 Then
            ShowInputBox("Add New Type")
            If CustomInputBox.OK Then
                Dim index As Integer = Fire_Type.Items.Count
                ' add new item to XML
                AddNewItemToXML("Type", CustomInputBox.Text)
                ' update the control source

                ' update the selected index
                'cb.SelectedIndex = index
            End If
        End If

Open in new window


and added

    Private Sub AddNewItemToXML(ByVal node As String, ByVal id As String)
        Dim d As New XmlDocument
        d.Load(DATA_FILE)

        Dim docroot As XmlNode = d.DocumentElement

        Dim root As XmlNode = docroot.SelectSingleNode(node)

        Dim child As XmlNode = d.CreateElement(node)

        Dim attribute As XmlAttribute = d.CreateAttribute("id")
        attribute.InnerText = id
        child.Attributes.Append(attribute)

        root.AppendChild(child)

        d.Save(DATA_FILE)


    End Sub

Open in new window


and that's where I'm at currently.

I now need to refresh the combobox source, and set the correct index on the combobox.

For right now, the item added will always be added at the end of the list.  I'll figure out sorting later if I decide it needs it.
0
 
AshokCommented:
' update the control source

cb.Items.Refresh()
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

 
sgaggerjAuthor Commented:
Thanks for the post! Good to know I was at least going in the right direction!

In my 2nd post, I added to XML directly and it works.

From what I can see, I have one of two options -

1) Continue that way, which would mean I need to refresh the binding of the combobox, and haven't found/figured out a way to do that

or

2) Use ObservableCollection as you mentioned, however I've never worked with observablecollection, and unsure where to start.  If, when using OC, I add something to the OC, does it a) add to the combobox (refresh) AND to XML?
 would you be able to provide a simple example?
0
 
sgaggerjAuthor Commented:

' update the control source

cb.Items.Refresh()

I had tried that after getting the new item added to XML, and it doesn't reload/refresh what was added to XML.
0
 
AshokCommented:
If, when using OC, I add something to the OC, does it a) add to the combobox (refresh) AND to XML?

a) Yes

b) No
0
 
sgaggerjAuthor Commented:
OK, so I would need to add to XML (as I'm doing) and to the OC.  Cool. good to know.

On to the OC, if you have any good/simple examples that'd be a huge help.  I'm googling now..
0
 
AshokCommented:
See answer in this post (it is in C#), but logic is same.

http://stackoverflow.com/questions/14506498/wpf-property-binding-doesnt-update-at-run-time
0
 
sgaggerjAuthor Commented:
Thanks!  

I was just reading through this:

http://www.telerik.com/help/wpf/gridview-loading-data-from-xml.html
0
 
AshokCommented:
I am at work and do not have .NET.
I will try to give you more help after I am home.

By the way, I code in C#.  Also, there is very good code converter at

http://converter.telerik.com/

HTH
Ashok
0
 
AshokCommented:
http://www.telerik.com/help/wpf/gridview-loading-data-from-xml.html

Above is good for loading data once, but it does not have PropertyChanged event which is what you need.
0
 
sgaggerjAuthor Commented:
No worries Ashok, I'm about to head home now anyhow and will be away for a few days.  

Any help you can give is greatly appreciated, and I can read/translate most C# on the fly as I'm somewhat versed in it, but still prefer VB as that's what I'm better at so C# code won't confuse me (too much!)

Thanks again!

And yea - I love that converter!
0
 
sgaggerjAuthor Commented:
OK, I'm back and ready to take on this.  Let me know what your thoughts on this were.

Thanks!
0
 
AshokCommented:
sgaggerj,

I do not know if / when I will have some free time to work on this.

Thanks,
Ashok
0
 
sgaggerjAuthor Commented:
No problem Ashok,

thanks for your help thus far - if you come across any examples in vb or c# that you think might help as well, let me know.  I'll go back and review the link you posted earlier

(http://stackoverflow.com/questions/14506498/wpf-property-binding-doesnt-update-at-run-time)

Thanks again!
0
 
sgaggerjAuthor Commented:
Finally got a working system, unfortunately couldn't get the OC working but I wrote my own that seems to work.

Thanks!
0
 
AshokCommented:
Glad to hear that you got it working!

Thanks,
Ashok
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.