XML文件和GUI之间的数据绑定

时间:2010-02-02 21:13:41

标签: wpf linq data-binding

我的小应用程序问题在概念上非常简单。我有一个XML文件,基本上只是将字符串映射到字符串。


冗长的解释警告


示例文件看起来像这样:

<Candies>
  <Sees>Box1</Sees>
  <Hersheys>Box2</Hersheys>
  <Godiva>Box3</Godiva>
</Candies>

虽然我可以使用不同的架构,例如:

<Candies>
  <Candy>
    <Name>Sees</Name>
    <Location>Box1</Location>
  </Candy>
</Candies>

......我选择不这样做,因为前者没有任何可预见的不良副作用。

在后面的代码中,我将XML文件的内容加载到带有LINQ的XDocument中。我还定义了一个List变量,因为这是我将GUI数据绑定到的。 CandyLocation看起来像这样:

public class CandyLocation
{
  public string Brand { get; set; }
  public string Location { get; set; }
}

我的简单GUI就是这样:

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="Auto" Width="Auto">

    <Page.Resources>
        <DataTemplate x:Key="CandyTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBox Grid.Column="0" Text="{Binding Brand}" Margin="3"></TextBox>
                <ComboBox Grid.Column="1" SelectedValue="{Binding Location}" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Page}}, Path=DataContext.LocationNames}" Text="{Binding Location, Mode=TwoWay}" Margin="3"></ComboBox>
            </Grid>
        </DataTemplate>
    </Page.Resources>

    <DockPanel>
        <Button DockPanel.Dock="Bottom" Margin="3" Command="{Binding SaveCandiesCommand}">Apply Changes</Button>
        <Button DockPanel.Dock="Bottom" Margin="3" Command="{Binding AddNewCandyCommand}">Add Candy</Button>
        <ListBox DockPanel.Dock="Top" ItemsSource="{Binding CandyLocations}" ItemTemplate="{StaticResource CandyTemplate}" />
    </DockPanel>
</Page>

所以概述是这样的:

应用程序加载然后使用LINQ加载XML文件。当呈现GUI时,它调用“GetCandyLocations”,它遍历XML数据并使用XML文件的内容填充List对象。在初始加载XML时,GUI正确呈现(即糖果品牌及其位置正确显示),但这就是成功故事结束的地方。


如果我从一个空白的XML文件开始并添加一个品牌,我会通过向我的XDocument根添加一个新的XElement来实现。然后我调用OnPropertyChanged(“CandyLocations”)来进行GUI更新。 Location的初始值为“”,因此用户可以从组合框中选择有效位置。问题是,我无法弄清楚如何正确选择数据绑定,这样我就可以更新XElement值。因此,当我保存糖果位置时,一切都以空白位置值结束。此外,只要用户点击添加糖果,所有以前选择的位置组合框都会被清空。

总结:

  1. 我应该如何处理GUI中的选择更改?我在这个应用程序中使用MVVM,所以我避免使用ComboBox的SelectionChanged事件。
  2. 有没有办法直接从GUI数据绑定到XDocument?我还没有尝试过,但最好避免使用多个数据源(即用于序列化的XDocument和用于GUI渲染的List)。也许我可以让getter返回LINQ查询的结果并将其与值转换器???
  3. 配对
  4. 如果您要编写此应用程序,您将如何更改我的实现?我还在学习MVVM和WPF,所以任何建议都会很棒。
  5. 谢谢!

1 个答案:

答案 0 :(得分:1)

在您的ComboBox上,您可能会在SelectedValue和Text属性之间发生冲突。文本通常仅与IsEditable =“True”一起使用。尝试使用SelectedItem:

<ComboBox SelectedItem="{Binding Location}" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Page}}, Path=DataContext.LocationNames}" ></ComboBox>

如果要直接使用XDocument作为数据源,可以使用它(假设XDocument从VM公开为AvailableLocations):

<ComboBox ItemsSource="{Binding Path=AvailableLocations.Root.Elements}" SelectedValue="{Binding Location}"
          SelectedValuePath="Value" DockPanel.Dock="Top" DisplayMemberPath="Value"/>

如果您更喜欢显示公司名称,只需将DisplayMemberPath更改为“名称”。

同时尝试使用ObservableCollection而不是CandyLocations的List,这样您就可以在添加或删除项目时获得自动更改通知。