TwoWay将WPF ComboBox绑定到XDocument

时间:2013-05-02 10:27:46

标签: wpf data-binding combobox linq-to-xml

我有一个绑定到XDocument的ComboBox,它不会写回值更改:

teams.xml

<?xml version="1.0" encoding="utf-8" ?>
<teams>
  <team>
    <name>Team A</name>
    <leader>C</leader>
    <members>
      <member>A</member>
      <member>B</member>
      <member>C</member>
    </members>
  </team>
  <team>
    <name>Team B</name>
    <leader>B</leader>
    <members>
      <member>B</member>
      <member>D</member>
      <member>E</member>
    </members>
  </team>
</teams>

MainWindow.xaml

<Window x:Class="Teamleader.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
    <Grid>
        <DataGrid Name="grid" ItemsSource="{Binding}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Team" Binding="{Binding Path=Element[name].Value}"></DataGridTextColumn>
                <DataGridTemplateColumn Header="Leader">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding Path=Element[members].Descendants, PresentationTraceSources.TraceLevel=High}"
                                      SelectedValue="{Binding Path=Element[leader].Value, PresentationTraceSources.TraceLevel=High, Mode=TwoWay}"
                                      SelectedValuePath="Value"
                                      DisplayMemberPath="Value"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Header="Leader Text (only for testing)" Binding="{Binding Path=Element[leader].Value, Mode=TwoWay}"></DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
        <Button Content="Save" HorizontalAlignment="Right" VerticalAlignment="Bottom" Click="SaveButton_Click" />
    </Grid>
</Window>

MainWindow.xaml.cs

namespace Teamleader
{
    public partial class MainWindow : Window
    {
        private XDocument doc;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            doc = XDocument.Load("teams.xml");

            var teams = from team in doc.Root.Descendants("team") select team;

            grid.DataContext = teams.ToList();
        }

        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            doc.Save("teams-output.xml");
        }
    }
}

当我通过单击更改ComboBox的SelectedItem时,我的OutputWindow向我显示以下四行:

  

System.Windows.Data信息:41:BindingExpression路径错误:   为'对象'找不到'值'属性,因为数据项为空。   这可能是因为数据提供者没有生成任何数据   然而。 BindingExpression:路径=值;的DataItem = NULL;目标元素是   'ComboBox'(Name =''); target属性是'NoTarget'(类型'Object')

     

System.Windows.Data信息:20:BindingExpression不能   由于缺少信息而检索值。   BindingExpression:路径=值;的DataItem = NULL;目标元素是   'ComboBox'(Name =''); target属性是'NoTarget'(类型'Object')

     

System.Windows.Data信息:21:BindingExpression不能   从null数据项中检索值。绑定时可能会发生这种情况   分离或绑定到没有值的Nullable类型时。   BindingExpression:路径=值;的DataItem = NULL;目标元素是   'ComboBox'(Name =''); target属性是'NoTarget'(类型'Object')

     

System.Windows.Data信息:10:无法使用获取值   绑定并且不存在有效的回退值;使用默认值。   BindingExpression:路径=值;的DataItem = NULL;目标元素是   'ComboBox'(Name =''); target属性是'NoTarget'(类型'Object')

当我更改ComboBox的SelectedItem时,相应的TextBox不会更改其值。当我更改TextBox中的值时,ComboBox立即适应(假设值在列表中)。此外,使用TextBox更改的值将写回XDocument。使用ComboBox更改值无效。

我的目标框架是.NET Framework 4.5,我的系统运行的是Windows7 x64。

我找到了ComboBox twoway binding with XElement,但是上面提到的修补程序适用于.NET 4.0 - 我想现在应该修复它。安装此修补程序不适用于我的系统。

我还找到了ComboBox.SelectedValue not updating from binding source。使用SelectedItem而不是SelectedValue给我一个System.InvalidOperationException告诉我,TwoWay或OneWayToSource绑定不能在只读属性'Item'上工作(类型为MS.Internal.Xml.Linq.ComponentModel.XDeferredSingleton)。

任何人都可以指出我的错误或告诉我.NET Framework 3.5中的错误是否仍然存在?

2 个答案:

答案 0 :(得分:1)

问题WPF ComboBox not updating source确实告诉我该怎么做。将UpdateSourceTrigger=PropertyChanged添加到我的SelectedValue绑定中可以解决问题:

<ComboBox ItemsSource="{Binding Path=Element[members].Descendants}"
          SelectedValue="{Binding Path=Element[leader].Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
          SelectedValuePath="Value"
          DisplayMemberPath="Value"/>

我不知道为什么,但它就像一个魅力。

感谢“相关”-sidebar!

答案 1 :(得分:1)

UpdateSourceTrigger=PropertyChanged仅适用于.NET&lt; 4.5和KB2328886或.NET 4.5及更高版本的修补程序。要使用没有此修补程序的旧框架修复此问题,请尝试此操作以手动触发所需的事件:

<ComboBox ItemsSource="{Binding Path=Element[ActionOptions].Descendants}"
            SelectedValue="{Binding Path=Element[CurrentActionOption].Value, Mode=TwoWay}"
            SelectedValuePath="Value"
            SelectionChanged="SelectedIndexChanged"
            DisplayMemberPath="Value"
            Visibility="{Binding Path=Element[ActionOptionsVisibility].Value}"/>
private void SelectedIndexChanged(object sender, RoutedEventArgs e)
{
    var bindingExpression = ((ComboBox)sender).GetBindingExpression(ComboBox.SelectedValueProperty);
    bindingExpression.UpdateSource();
}