Как правильно заменить статический XmlDataProvider в пользовательском контроле WPF динамическим набором данных? - PullRequest
5 голосов
/ 08 апреля 2011

Вопрос, возможно, потребуется отредактировать, поскольку я не думаю, что обязательно знаю лучший способ сделать это.

Текущая конфигурация моего WPF usercontrol.У меня есть XmlDataProvider, который содержит некоторые статические XML-элементы, которые я использую для заполнения элемента управления TreeView.В настоящее время я использую HierarchicalDataTemplate для привязки к TreeViewItem

    <HierarchicalDataTemplate x:Key="SiteTemplate" ItemsSource="{Binding XPath=pci}">
        <TextBlock Text="{Binding XPath=@Name}"/>
    </HierarchicalDataTemplate>
    <Style TargetType="TreeViewItem">
        <Setter Property="IsExpanded" Value="True"/>
    </Style>

Элемент управления TreeView

 <TreeView ItemsSource="{Binding Source={StaticResource SharePointSites}}" 
                              ItemTemplate="{StaticResource SiteTemplate}" 

Я хотел бы заменить текущий статический ресурс данными, которые загружаются из XML-файла во время выполнения,Кроме того, я хочу, чтобы пользователь мог изменять узлы древовидной структуры во время выполнения и записывать эти значения обратно в один и тот же XML-файл.Я читал об использовании шаблона MVVM и создании класса IObservable.Может ли кто-нибудь указать мне правильное направление?

Редактировать: Возможно, я задал этот вопрос неоптимальным образом.Кто-нибудь может порекомендовать улучшения или внести изменения, чтобы улучшить качество вопроса в любом случае?

1 Ответ

3 голосов
/ 22 июля 2011

У меня нет доступа к моей среде Visual Studio, поэтому приведенный ниже код будет полон ошибок компиляции ... Поэтому, пожалуйста, воспринимайте это как псевдокод ...

Предположим, что ваша структура XML похожа на эту....

<MyItem Name="Root"> 
    <MyItem Name="ABC"/> 
    <MyItem Name="PQR"> 
        <MyItem Name="IJK"/> 
    </MyItem> 
    <MyItem Name="XYZ"/> 
</MyItem> 
  1. Свяжите свой ItemsSource через конвертер, скажем, MyXmlToObjectDataSourceConverter.

    <TreeView ItemsSource="{Binding Source={StaticResource SharePointSites},
           Converter={StaticResource MyXmlToObjectDataSourceConverter}}" ... />
    
  2. В MyXmlToObjectDataSourceConverter.Convert ()метод возвращает это ...

    public object Convert(...) 
    { 
        return new ObservableCollection<XmlNodeWrapper>(
            ((XmlDataProvider)value).Document.SelectNodes("MyItem").Select( 
                d => new XmlNodeWrapper(d)).ToList()) 
    }
    
  3. Класс XmlNodeWrapper будет поддерживать «узел» внутри, так что когда обновления происходят через свойство Setters, вы можете обновить атрибут на основе узла обратно ..вот так ...

    public class XmlNodeWrapper : INotifyPropertyChanged
    { 
        private XmlNode node; 
        private ObservableCollection<XmlNodeWrapper> children; 
    
        public XmlNodeWrapper(XmlNode node) 
        { 
            this.node = node; 
        } 
    
        public ObservaleCollection<XmlNodeWrapper> Children 
        { 
            get 
            { 
                if (children == null) 
                { 
                    this.children 
                        = new ObservableCollection<XmlNodeWrapper>( 
                            this.node.ChildNodes.Select( 
                                d => new XmlNodeWrapper(d)).ToList()); 
                } 
    
                return children; 
            } 
        } 
    
        public string Name 
        { 
            get 
            { 
                return node.Attributes["Name"]; 
            } 
    
            set 
            { 
                node.Attributes["Name"] = value; 
                this.PropertyChanged["Name"]; 
            } 
        } 
    
        public event PropertyChangedEventHandler PropertyChanged; 
    
        private void PropertyChanged(String info) 
        { 
            if (PropertyChanged != null) 
            { 
                PropertyChanged(this, new PropertyChangedEventArgs(info)); 
            } 
        }
    } 
    
  4. Затем замените все атрибуты XPath в вашем XAML стандартным путем.

    <HierarchicalDataTemplate x:Key="SiteTemplate"
        ItemsSource="{Binding Path=Children}"> 
            <TextBlock Text="{Binding Path=Name}"/> 
    </HierarchicalDataTemplate>
    
...