using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using System.Xml.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using log4net; using log4net.Config; namespace ExampleCS { /// <summary> /// Window1.xaml の相互作用ロジック /// </summary> public partial class Window1 : Window { private static readonly ILog log = LogManager.GetLogger(typeof(Window1)); public Window1() { // BasicConfigurator replaced with XmlConfigurator. XmlConfigurator.Configure(new System.IO.FileInfo(@"log4net.xml")); InitializeComponent(); blog = XDocument.Load(BLOGURL); } XDocument blog = new XDocument(); const string BLOGURL = "http://utsuutsu.blogspot.com/feeds/posts/default"; #region Event void Window1_Loaded(object sender, RoutedEventArgs e) { FillListBox(); } private void entryListBox_Changed(object sender, SelectionChangedEventArgs e) { if (entryListBox.SelectedIndex != -1) { XElement element = ((ListBoxItem)entryListBox.SelectedItem).Tag as XElement; if (element != null) { titleText.Text = element.Element("{http://www.w3.org/2005/Atom}title").Value; urlText.Text = element.Elements("{http://www.w3.org/2005/Atom}link"). Single(el => el.Attribute("rel").Value == "alternate").Attribute("href").Value; dateText.Text = element.Element("{http://www.w3.org/2005/Atom}updated").Value; bodyText.Text = element.Element("{http://www.w3.org/2005/Atom}content").Value; } } } private void updateButton_Click(object sender, RoutedEventArgs e) { } #endregion #region private void FillListBox() { entryListBox.Items.Clear(); var nodes = blog.Descendants("{http://www.w3.org/2005/Atom}entry"); foreach (XElement element in nodes) { ListBoxItem item = new ListBoxItem(); item.Tag = element; item.Content = element.Element("{http://www.w3.org/2005/Atom}title").Value; entryListBox.Items.Add(item); } } #endregion } }log4netのコードとかもそのままにしてるけど、気にしないでください。 こっちはこれまでの学習の効果があってすぐにできた。 問題はXAMLだけを利用する(バインディングですべて解決)パターンだった。 XmlDataProviderでフィードを読ませてバインディングしていけばいいのかと思いきや、namespace-uriを指定する方法がわからない。。。 なんとなくクラスの関連上XmlNamespaceManagerがそれに該当するんだろうということはわかったんだけど、これってクラス->オブジェクトなんでXAMLに直にuriを書くわけにはいかず。。。(stringになるもんね) どうすりゃいいのかわからず、 あっちこっち探し回っているとMSDNのフォーラムに対応方法が載っていた。 Resources上でXmlNamespaceMappingCollectionにKeyを付けてXmlNamespaceMappingを生成するというやり方で、Key名を使ってXmlDataProviderにバインディングすることができるらしい。 で、やってみた結果がこれ(今度はXAMLだけで逆にC#側のコーディングは0です。)
<Window x:Class="ExampleCS.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ExsampleCS"> <StackPanel> <StackPanel.Resources> <XmlNamespaceMappingCollection x:Key="mapping"> <XmlNamespaceMapping Uri="http://www.w3.org/2005/Atom" Prefix="rss"/> </XmlNamespaceMappingCollection> <XmlDataProvider x:Key="RssFeed" XmlNamespaceManager="{StaticResource mapping}" Source="http://utsuutsu.blogspot.com/feeds/posts/default" /> </StackPanel.Resources> <TextBlock HorizontalAlignment="Center" FontWeight="Bold"> BlogEditor </TextBlock> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <ListBox Name="entryListBox" Height="300" ItemsSource="{Binding Source={StaticResource RssFeed}, XPath=//rss:entry}"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding XPath=rss:title}"/> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <Grid Width="500" Margin="5" DataContext="{Binding ElementName=entryListBox, Path=SelectedItem}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="50"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="25"/> <RowDefinition Height="25"/> <RowDefinition Height="25"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Grid.Column="0">Title:</TextBlock> <TextBox Binding.XmlNamespaceManager="{StaticResource mapping}" Grid.Row="0" Grid.Column="1" Name="titleText" Text="{Binding XPath=rss:title}" /> <TextBlock Grid.Row="1" Grid.Column="0">Url:</TextBlock> <TextBox Binding.XmlNamespaceManager="{StaticResource mapping}" Grid.Row="1" Grid.Column="1" Name="urlText" Text="{Binding XPath=rss:link/@href[1]}"/> <TextBlock Grid.Row="2" Grid.Column="0">Date:</TextBlock> <TextBox Binding.XmlNamespaceManager="{StaticResource mapping}" Grid.Row="2" Grid.Column="1" Name="dateText" Text="{Binding XPath=rss:updated}"/> <TextBlock Grid.Row="3" Grid.Column="0">Body:</TextBlock> <TextBox Binding.XmlNamespaceManager="{StaticResource mapping}" Grid.Row="3" Grid.Column="1" Name="bodyText" TextWrapping="Wrap" Text="{Binding XPath=rss:content}"/> </Grid> </StackPanel> </StackPanel> </Window>XmlDataProviderにバインディングしてListBoxにバインディングするところまでは問題なかったんだけど、最後にイベント連動のGrid側のDataContextの内容がTextBox上で取得できないという状態になり、 またまた悪戦苦闘。。。 やっぱり、namespace-uriがらみだった。。。 TextBoxにBinding.XmlNamespaceManager="{StaticResource hoge}"って実装が必要なんだそうだ。。。 まあ、最終的にはこんなのができた。 Application側(app.xaml)でスタイルをあれこれすればもうちょい見た目もよくなるだろう。。。 オンラインセミナーで「Expression Blend」とかいうツールの紹介がされていた。デザインに関してはこっちでやるといいよ~とMSの人は言っていた。 また、機会があればそっちも見てみようと思う。
ひとつだけ腑に落ちない部分がある。 それは、XAML上だけで表現するときにXPathで属性の条件付き取得の式がちゃんと評価されてないんじゃないの?って思うところだ。
rss:link[@ref='hoge']/@hrefこれで、linkタグの中でref属性がhogeのhref属性値が取得できると思うんだけど、何か違うのかな?? LINQでSingleを使った時には問題なかったんだけど。。。(Singleは1つ以外だとExceptionが発生する)
0 件のコメント:
コメントを投稿