2013-05-02 3 views
0

У меня есть ComboBox привязан к XDocument и не записывать изменения значений:TwoWay связывают WPF ComboBox с XDocument

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"); 
     } 
    } 
} 

Когда я изменяю SelectedItem из ComboBox, нажав на него, мой OutputWindow показывает мне следующие четыре строки:

System.Windows.Data Information: 41 : BindingExpression path error: 'Value' property not found for 'object' because data item is null. This could happen because the data provider has not produced any data yet. BindingExpression:Path=Value; DataItem=null; target element is 'ComboBox' (Name=''); target property is 'NoTarget' (type 'Object')

System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=Value; DataItem=null; target element is 'ComboBox' (Name=''); target property is 'NoTarget' (type 'Object')

System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=Value; DataItem=null; target element is 'ComboBox' (Name=''); target property is 'NoTarget' (type 'Object')

System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=Value; DataItem=null; target element is 'ComboBox' (Name=''); target property is 'NoTarget' (type 'Object')

Когда я изменяю SelectedItem в ComboBox, соответствующий 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 все еще существует?

+0

Не отложенной загрузки проблемы? Часть сообщения об ошибке читает «Это может произойти, потому что поставщик данных еще не выдал никаких данных».? Попробуйте перебрать все команды и всех руководителей команд, прежде чем назначать список Datacontext. Помогает ли это? – milanio

+0

Я не пробовал. В настоящее время я думаю, что сообщения - это просто сообщения, ничего важного. В конце концов, он работает, когда я добавляю 'UpdateSourceTrigger = PropertyChanged', см. Мой ответ ниже. –

ответ

0

Вопрос 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"/> 

Я не знаю, почему, но это работает как шарм.

Благодаря «родственной» боковой панели!

1

UpdateSourceTrigger=PropertyChanged работает только с .NET < 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(); 
} 
Смежные вопросы