2014年4月24日木曜日

つながる図書館: コミュニティの核をめざす試み 猪谷 千香 (著)

たまたまですが、「つながる図書館」昨日の新聞で紹介されてましたね。

今朝読了しました。内容をネタバレしすぎない程度に纏めてみます。

公立無料貸本屋
2000年ごろから、ベストセラーとなった本が同一図書館に数十冊所蔵されていることがあり、作家が数千万単位の損失を被っています。故に図書館は「公立無料貸本屋」と揶揄されました。

各図書館はこの批判を受け、図書館でしか提供できないサービス、コンテンツなどを模索し始めます。


  • 住みたいと言われる武蔵野プレイス
  • セカンドオフィスになる千代田図書館
  • 町民主導で出来上がったまちとしょテラソ
  • レシピ本だけでなくベーカリーまで貸し出した鳥取県立図書館

等々。他にもたくさん。

指定管理者制度
バブル崩壊後、予算は削減されます。
それとは反対に休日や夜遅く(22時)まで利用したいというニーズは加速します。
対応するには公務員制度の範疇を超えるのでアウトソーシングせざるをえません。
それを可能にするために「指定管理者制度」が出来ました。
これは営利企業やNPO法人に運営委託出来るようになるための制度です。

成功例として千代田図書館が冒頭に紹介されていますが、斬新すぎていい意味でも悪い意味でも炎上したのが武雄市図書館です。2012年、武雄市図書館の運営はカルチュア・コンビニエンス・クラブ(CCC)が行うこととなりました。いわゆる TSUTAYA グループなのです。なので、ここにはスタバとか TSUTAYA、本屋が入っています。貸し出し時に3ポイントくれてやるというのです。ゆっくりお茶しながら本を読める施設なんて、すごくいいじゃんて思うのですが、Tカードで管理されるということは、図書館としてはご法度な個人情報を他で扱われる危険性があるとか、そもそも図書館は無料が基本なのに営利企業のシステムまで組み込んでいいの?などという批判があるようです。

感想
私個人的にすごく思ったことですが、少ない予算を増やすならカフェとかをどんどん出店させて出店料などを徴収すればいいのではなかろうか?そういう営利的なのが法律で規制されているのであれば、それに準じようとするのではなく、その時代に合わなくなってきている法自体を見直した方がいいのではないか?と思う。思うだけなので、問題はもっと複雑だから簡単にはいかないのだろうけれども。

問題提起としては素晴らしいですね。武雄市図書館。ところで武雄市が何県なのか最後のほうまで全く触れられず、こないだ仕事で「武雄JCT」の話題があったので、恐らく九州だろうなと思いながら読んでましたが、機会があれば行ってみるといいと勧められました。ちょっと不親切だなと思いました。

その他
地域に保管されている歴史的資料などをデジタルアーカイブ化し、WEBで閲覧できるシステムを進めていたり、Facebook アカウントで図書を共有、借りたりするシステムが出来たり、様々な試みが紹介されていました。各図書館の新しい試みで、地元民以外の人たちが集まってきており、その地にお金を落としていっているようなので、図書館としての収益はないかもしれませんが、地方が潤うというメリットは大いにあるようです。


余談
伊万里市民図書館の「図書館の自由に関する宣言」や、日野市立図書館の「移動図書館ひまわり号」の精神なども紹介されていて、有川浩氏の図書館戦争のルーツを知ることが出来ました。

[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とかにバインドさせて編集後、更新ボタンとかで要素の属性情報を全て更新すればいいかな。




[WPF][C#]XMLデータをTreeViewに表示 その2

XmlDataProvider で XML データを TreeView に表示する方法を紹介しましたが、今回は ObjectDataProvider を使用して、XDocument として XML データを TreeView に表示する方法を紹介します。

XMLをロードして TreeView に表示する
子要素がない場合は値を横に表示する様にItemTemplateを変更しています。

[Namespace]
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:linq="clr-namespace:System.Xml.Linq;assembly=System.Xml.Linq"

[Resource]
        <ObjectDataProvider x:Key="xmlDocument" ObjectType="{x:Type linq:XDocument}" MethodName="Load">
            <ObjectDataProvider.MethodParameters >
                <sys:String>Data\70_04_01_091210_fure-1.xml</sys:String>
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
        <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>

[Layout]
    <Grid>
        <TreeView Name="treeView" Margin="5"
                  ItemsSource="{Binding Path=Root.Elements, Source={StaticResource xmlDocument}}"
                  ItemTemplate= "{StaticResource XmlTemplate}"
                  >
        </TreeView>
    </Grid>

TreeView に XML データを表示

Root の表示
問題があって、これだと XML のルートが表示されません。仕方がないので、ここはコードで小細工をする必要があります。コンストラクタとかで、下記処理を書きます。

    var element = XElement.Load(@"Data\70_04_01_091210_fure-1.xml");
    var document = new XDocument(new XElement("Root", element));
    treeView.ItemsSource = document.Root.Elements();


やっていることは、XDocument でルートを自作して、子要素に読み込んだXElement を追加してあげているだけです。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>
        <TreeView Name="treeView" Margin="5"
                  ItemTemplate= "{StaticResource XmlTemplate}"
                  >
        </TreeView>
    </Grid>

TreeView に XML データを表示

はい、ルートが表示されるようになりました。
編集は次回に続きます。






[WPF][C#]XMLデータをTreeViewに表示 その1

XMLデータをそのまま TreeView に表示してみたいと思います。

ソリューションにXMLファイル追加
XMLデータを作るのが面倒だったので、「気象庁防災情報XMLフォーマット 技術資料」のサンプルデータをお借りします。

ソリューションに追加し、下記設定を行います。
ビルド アクション   :コンテンツ
出力ディレクトリにコピー:新しい場合はコピーする

XMLをソリューションに追加


XMLをロードして TreeView に表示する
C#で書くのが普通ですが、DataProvider を使えば XAML だけで出来ます(Silverlightは不可)。今回はXmlDataProviderを使ったやり方でロードしましょう。

    <Window.Resources>
        <XmlDataProvider x:Key="xmlDataProvider" Source="Data\70_04_01_091210_fure-1.xml" ></XmlDataProvider>
    </Window.Resources>
    <Grid>
        <TreeView Margin="5"
                  ItemsSource="{Binding Source={StaticResource xmlDataProvider}, XPath=*}"
                  />

これだけだと、XML の Value だけが抽出されて表示されてしまいます。

TreeView に XML データを表示


ItemTemplate を定義してあげます。

    <Window.Resources>
        <XmlDataProvider x:Key="xmlDataProvider" Source="Data\70_04_01_091210_fure-1.xml" ></XmlDataProvider>
        <HierarchicalDataTemplate x:Key="NodeTemplate">
            <StackPanel Orientation="Horizontal">
                <Grid>
                    <TextBlock x:Name="nameTextBlock" Visibility="Visible" Text="{Binding Path=Text, ElementName=nameTextBox}" />
                </Grid>
            </StackPanel>
            <HierarchicalDataTemplate.ItemsSource>
                <Binding XPath="child::node()" />
            </HierarchicalDataTemplate.ItemsSource>
            <HierarchicalDataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=NodeType}" Value="Text">
                    <Setter TargetName="nameTextBlock" Property="Text" Value="{Binding Path=Value, Mode=OneTime}" />
                    <Setter TargetName="nameTextBlock" Property="FontWeight" Value="Bold" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=NodeType}" Value="Element">
                    <Setter TargetName="nameTextBlock" Property="Text" Value="{Binding Path=Name, Mode=OneTime}" />
                </DataTrigger>
            </HierarchicalDataTemplate.Triggers>
        </HierarchicalDataTemplate>
    </Window.Resources>
    <Grid>
        <TreeView Margin="5"
                  ItemsSource="{Binding Source={StaticResource xmlDataProvider}, XPath=*}"
                  ItemTemplate="{StaticResource NodeTemplate}"
                  />
    </Grid>



TreeView に XML データを表示

いい感じでツリー表示されるようになりました。デフォルトはツリー閉じている状態なので、最初から全て開いておきたければ、リソースに下記を追加するだけでOKです。

        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="True"/>
        </Style>

TreeView に XML データを表示

Attributes(属性値)をここに表現するのは難しいので、ここでは割愛します。要素がコメントの場合は色を変えたいとかであれば、下記トリガーの設定でいけます。

                <DataTrigger Binding="{Binding Path=NodeType}" Value="Comment">
                    <Setter TargetName="nameTextBox" Property="Text" Value="{Binding Path=Value, Mode=OneTime}" />
                    <Setter TargetName="nameTextBlock" Property="Foreground" Value="#FF00FF00" />

                </DataTrigger>


閲覧だけなら XmlDataProvider で十分なのですが、編集には向いていないようです。
編集するなら XDocument で扱う方がよさそうです。XDocument として読み込むには ObjectDataProvider が使えますが、それはまた次回。


関連