Solved

WPF ComboBox TwoWay binding with XML

Posted on 2013-12-19
21
1,210 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
Comment Utility
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
Comment Utility
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
Comment Utility
' update the control source

cb.Items.Refresh()
0
 
LVL 1

Author Comment

by:sgaggerj
Comment Utility
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
Comment Utility

' 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 1

Author Comment

by:sgaggerj
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Glad to hear that you got it working!

Thanks,
Ashok
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
Entering a date in Microsoft Access can be tricky. A typo can cause month and day to be shuffled, entering the day only causes an error, as does entering, say, day 31 in June. This article shows how an inputmask supported by code can help the user a…
The viewer will learn the benefit of using external CSS files and the relationship between class and ID selectors. Create your external css file by saving it as style.css then set up your style tags: (CODE) Reference the nav tag and set your prop…
HTML5 has deprecated a few of the older ways of showing media as well as offering up a new way to create games and animations. Audio, video, and canvas are just a few of the adjustments made between XHTML and HTML5. As we learned in our last micr…

763 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now