2014年4月24日木曜日

[WPF][C#]XMLデータをTreeViewで編集

XML データを TreeView に表示できるところまでやりました。次は編集ですね。

編集画面追加
TreeView 上で編集するのは難しそうなので、編集エリアを設けて選択した要素を操作するのがよさそうです(MVVMパターンとかバインドとか面倒だったので、そちらは割愛させて頂きます。)。そして、ごめんなさい、色々と面倒くさくなってきたので、一気に貼り付けます。


[XAML]
    <Window.Resources>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="True" />
        </Style>
        <HierarchicalDataTemplate x:Key="XmlTemplate" ItemsSource="{Binding Path=Elements}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Name="nameTextBlock" Text="{Binding Path=Name.LocalName}"/>
                <TextBlock Name="valueTextBlock" FontWeight="Bold" Margin="5,0" />
            </StackPanel>
            <HierarchicalDataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=HasElements}" Value="False">
                    <Setter TargetName="valueTextBlock" Property="Text" Value="{Binding Path=Value}" />
                </DataTrigger>
            </HierarchicalDataTemplate.Triggers>
        </HierarchicalDataTemplate>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="300"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <!--表示エリア-->
        <TreeView Name="treeView" Margin="5"
                  ItemTemplate= "{StaticResource XmlTemplate}"
                  SelectedItemChanged="treeView_SelectedItemChanged" 
                  >
        </TreeView>
        
        <!--編集エリア-->
        <StackPanel Grid.Column="1" >
            <GroupBox Header="要素名" Margin="5">
                <StackPanel Orientation="Horizontal" Margin="0,5">
                    <TextBox Name="nameTextBox" Text="{Binding Path=Name.LocalName}" Width="80" />
                    <Button Content="追加" Name="addElementButton" Click="addElementButton_Click"  Width="50" Margin="5,0,0,0"/>
                    <Button Content="更新" Name="updateNameButton" Click="updateNameButton_Click"  Width="50" Margin="5,0,0,0"/>
                    <Button Content="削除" Name="delElementButton" Click="delElementButton_Click"  Width="50" Margin="5,0,0,0"/>
                </StackPanel>
            </GroupBox>

            <GroupBox Header="" Margin="5" Name="valueGroup">
                <StackPanel Orientation="Horizontal" Margin="0,5">
                    <TextBox Name="valueTextBox" Text="{Binding Path=Value}" Width="80" />
                    <Button Content="更新" Name="updateValueButton" Click="updateValueButton_Click"  Width="50" Margin="5,0,0,0"/>
                </StackPanel>
            </GroupBox>
        </StackPanel>

    </Grid>


[Code]
        /// <summary>
        /// 要素選択変更イベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            var element = e.NewValue as XElement;
            if (element != null)
            {
                nameTextBox.Text = element.Name.LocalName;
                if (!element.HasElements)
                {
                    // 子要素が無ければ値を編集できるようにする
                    valueTextBox.Text = element.Value;
                    valueGroup.Header = element.Name.LocalName;
                    valueGroup.IsEnabled = true;
                }
                else
                {
                    valueTextBox.Text = "";
                    valueGroup.Header = "";
                    valueGroup.IsEnabled = false;
                }
            }
        }

        /// <summary>
        /// 要素追加ボタン実行
        /// </summary>
        /// <remarks>
        /// 選択中要素に子要素を追加する
        /// </remarks>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void addElementButton_Click(object sender, RoutedEventArgs e)
        {
            var element = treeView.SelectedItem as XElement;
            if (!string.IsNullOrEmpty(nameTextBox.Text) && element != null)
            {
                XNamespace x = element.Name.Namespace;
                var newElement = new XElement(x + nameTextBox.Text) { Value = valueTextBox.Text };
                element.Add(newElement);
            }
        }

        /// <summary>
        /// 要素更新ボタン実行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void updateNameButton_Click(object sender, RoutedEventArgs e)
        {
            var element = treeView.SelectedItem as XElement;
            if (!string.IsNullOrEmpty(nameTextBox.Text) && element != null)
            {
                XNamespace x = element.Name.Namespace;
                element.Name = x + nameTextBox.Text;

                // ①子要素の有無をチェックしないと消えてしまう
                element.Value = valueTextBox.Text;

                // ②選択している要素が解除されてしまう
                treeView.Items.Refresh();
            }
        }

        /// <summary>
        /// 要素削除ボタン実行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void delElementButton_Click(object sender, RoutedEventArgs e)
        {
            var element = treeView.SelectedItem as XElement;
            if (element != null)
            {
                element.Remove();
            }
        }

        /// <summary>
        /// 値更新ボタン実行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void updateValueButton_Click(object sender, RoutedEventArgs e)
        {
            var element = treeView.SelectedItem as XElement;
            if (!string.IsNullOrEmpty(nameTextBox.Text) && element != null)
            {
                element.Value = valueTextBox.Text;
            }
        }


残件
残件とか課題としては、MVVM化とかコメントの①②があります。あと属性の編集もですかね。これは要素選択変更イベントで、属性があれば、名称と値のエンティティのリストを作成し、DataGridとかにバインドさせて編集後、更新ボタンとかで要素の属性情報を全て更新すればいいかな。




0 件のコメント:

コメントを投稿