Search code examples
wpfbindingxmldatasource

Binding to XMLDataProvider


Made a simple test project where i try to bind to a xmldatasource in a proto viewmodel

public partial class Window1 : Window
{
    //private XmlDataProvider _provider = new XmlDataProvider(); 
    private MyViewModel _myViewModel = new MyViewModel();
    public Window1()
    {
        InitializeComponent();
        this.DataContext = _myViewModel ;
    }    
}

public class MyViewModel
{    
    public MyViewModel()
    {
        LoadXMLData();
    }

    private XmlDataProvider _provider = new XmlDataProvider(); 
    public XmlDataProvider Reports
    {
        get { return _provider; }
        set { _provider = value; }
    }    

    private void LoadXMLData()
    {
        string filePath = Directory.GetCurrentDirectory() + @"\Reports2.xml";

        System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
        doc.Load(filePath);
        _provider.Document = doc;
        _provider.XPath = @"Reports/Report";
    }
}

If i try to bind a listbox like this. I get nothing

<ListBox x:Name="TeamsListBox" Margin="0,0,0,20" DockPanel.Dock="Left"
    ItemsSource="{Binding Reports}"
    ItemTemplate="{StaticResource teamItemTemplate}"
    IsSynchronizedWithCurrentItem="True"
    Visibility="Visible" SelectionMode="Single">
</ListBox>

If i instead change datacontext to

this.DataContext = _myViewModel.Reports

And listbox to

<ListBox x:Name="TeamsListBox" Margin="0,0,0,20" DockPanel.Dock="Left"
    ItemsSource="{Binding}"
    ItemTemplate="{StaticResource teamItemTemplate}"
    IsSynchronizedWithCurrentItem="True"
    Visibility="Visible" SelectionMode="Single">
</ListBox>

Then it works, how do i bind to the viewmodel so i can fill it with more than just on xmldatasource

If i put a breakpoint on property Report i can see that it is called when i do {Binding Reports} but the list is still empty.

UPDATE

I can do this binding in code and then it works

 Binding binding = new Binding();
            binding.Source = _myViewModel.Reports;
            binding.XPath = @"Reports/Report";
            TeamsListBox.SetBinding(ListBox.ItemsSourceProperty, binding);

Why cant i do that in XAML


Solution

  • Seems like i had some problems with the understanding of XPath and my general question was how to bind to a dynamic xmldataprovider in a viewmodel with xaml. Solved it like this.

    XML

    <?xml version="1.0" encoding="utf-8"?>
    <Reports xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <Report Id="AAAAA-ABBB">
        <DocId>30110001</DocId>
        <DocName>Report name1</DocName>
        <DocType>2010-01-01</DocType>
        <Status>1</Status>
        <CreatedById>1</CreatedById>
        <SiteId>1</SiteId>
        <Language>1</Language>
        <Updated>2011-01-01</Updated>
        <Published>2011-01-01</Published>
        <FilePath>c:\\reports\20011001.docx</FilePath>
      </Report>
      <Report Id="AAAAA-ABBC">
        <DocId>30110002</DocId>
        <DocName>Report name2</DocName>
        <DocType>2010-01-01</DocType>
        <Status>1</Status>
        <CreatedById>1</CreatedById>
        <SiteId>1</SiteId>
        <Language>1</Language>
        <Updated>2011-01-01</Updated>
        <Published>2011-01-01</Published>
        <FilePath>c:\\reports\20011001.docx</FilePath>
      </Report>
    </Reports>
    

    Window1

        <Window x:Class="WpfApplication2.Window1"
                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" 
                  Title="Window1" Height="300" Width="300">
            <Window.Resources>
    
                <DataTemplate x:Key="reportItemTemplate">
                    <StackPanel Orientation="Horizontal">
                    <Label Content="{Binding XPath=DocId}"/>
                        <Label Content="{Binding XPath=DocName}"/>
                    </StackPanel>
                </DataTemplate>
            </Window.Resources>
            <StackPanel  DataContext="{Binding LocalReports}" >
                <ListBox  
    
                ItemsSource="{Binding}"
                    ItemTemplate="{StaticResource reportItemTemplate}"
                             IsSynchronizedWithCurrentItem="True"
                             Visibility="Visible" SelectionMode="Single"
                    />
                <TextBox Text="{Binding XPath=DocId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                <TextBox Text="{Binding XPath=DocName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                <Button Content="Button" Height="23" Name="button1" Click="button1_Click" />
            </StackPanel>
    
        </Window> 
    

    Window1.xaml.cs

    namespace WpfApplication2
    {
        /// <summary>
        /// Interaction logic for Window1.xaml
        /// </summary>
        public partial class Window1 : Window
        {
            //private XmlDataProvider _provider = new XmlDataProvider(); 
            private MyViewModel _myViewModel = new MyViewModel();
    
            public Window1()
            {
                InitializeComponent();
    
                this.DataContext = _myViewModel;
    
    
            }
    
    
             private void button1_Click(object sender, RoutedEventArgs e)
             {
                 _myViewModel.Save();
             }
    
        }
    
        public class MyViewModel
        {
    
            public MyViewModel()
            {
                          }
    
            private XmlDataProvider _provider;
            public XmlDataProvider LocalReports
            {
    
                get
                {
                    String file = Directory.GetCurrentDirectory() + @"\Reports2.xml";
                    _provider = new XmlDataProvider()
                    {
                        Source = new Uri(file, UriKind.Absolute),
                        XPath = "Reports/Report"
                    };
                    return _provider;
                }
            }
    
    
    
            }
    
    
            public  void Save()
            {
                string source = _provider.Source.LocalPath;
                _provider.Document.Save(source);
            }
        }
    }