Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

WPF ComboBox TwoWay binding with XML

Posted on 2013-12-19
21
1,278 Views
Last Modified: 2014-02-04
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

0
Comment
Question by:sgaggerj
  • 9
  • 8
21 Comments
 
LVL 1

Author Comment

by:sgaggerj
ID: 39731961
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
 
LVL 13

Accepted Solution

by:
Ashok earned 500 total points
ID: 39738044
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
 
LVL 13

Expert Comment

by:Ashok
ID: 39738095
' update the control source

cb.Items.Refresh()
0
MIM Survival Guide for Service Desk Managers

Major incidents can send mastered service desk processes into disorder. Systems and tools produce the data needed to resolve these incidents, but your challenge is getting that information to the right people fast. Check out the Survival Guide and begin bringing order to chaos.

 
LVL 1

Author Comment

by:sgaggerj
ID: 39738102
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
 
LVL 1

Author Comment

by:sgaggerj
ID: 39738106

' 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
 
LVL 13

Expert Comment

by:Ashok
ID: 39738112
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
 
LVL 1

Author Comment

by:sgaggerj
ID: 39738126
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
 
LVL 13

Expert Comment

by:Ashok
ID: 39738128
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
 
LVL 1

Author Comment

by:sgaggerj
ID: 39738142
Thanks!  

I was just reading through this:

http://www.telerik.com/help/wpf/gridview-loading-data-from-xml.html
0
 
LVL 13

Expert Comment

by:Ashok
ID: 39738145
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
 
LVL 13

Expert Comment

by:Ashok
ID: 39738157
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
 
LVL 1

Author Comment

by:sgaggerj
ID: 39738160
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
 
LVL 1

Author Comment

by:sgaggerj
ID: 39751311
OK, I'm back and ready to take on this.  Let me know what your thoughts on this were.

Thanks!
0
 
LVL 13

Expert Comment

by:Ashok
ID: 39763180
sgaggerj,

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

Thanks,
Ashok
0
 
LVL 1

Author Comment

by:sgaggerj
ID: 39765072
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
 
LVL 1

Author Closing Comment

by:sgaggerj
ID: 39832560
Finally got a working system, unfortunately couldn't get the OC working but I wrote my own that seems to work.

Thanks!
0
 
LVL 13

Expert Comment

by:Ashok
ID: 39834154
Glad to hear that you got it working!

Thanks,
Ashok
0

Featured Post

Webinar: Aligning, Automating, Winning

Join Dan Russo, Senior Manager of Operations Intelligence, for an in-depth discussion on how Dealertrack, leading provider of integrated digital solutions for the automotive industry, transformed their DevOps processes to increase collaboration and move with greater velocity.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
ejb stateless example 2 25
Visual Studios 1 76
VB.Net - Not Sure if Multi-threading is What I Need 4 30
Error message when using PrintSocket.Send 7 18
A short article about problems I had with the new location API and permissions in Marshmallow
JavaScript has plenty of pieces of code people often just copy/paste from somewhere but never quite fully understand. Self-Executing functions are just one good example that I'll try to demystify here.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
The viewer will the learn the benefit of plain text editors and code an HTML5 based template for use in further tutorials.

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question