Windows Presentation Foundationプログラミングの間違い

Windows Presentation Foundationプログラミング

Windows Presentation Foundationプログラミング

サンプルを打ち込んでいるのですが、早速引っ掛かりました。

(追記) 以下を正誤表とします。見つけ次第追加していく予定。


ダウンロード出来るサンプルコードについて

http://www.sellsbrothers.com/writing/avbook/
ここからダウンロード出来ますが、このままだと日本語環境で動作しません。*.csprojファイルから、

<UICulture>en-US</UICulture>

の部分を削除する必要があります。


第3章のサンプルについて

このままだとNovCtpでコンパイル出来ません。以下の修正が必要です。

  1. ch03\NovCtp\ControlsExamples\MyLib\MyLib.csprojからSystem.Transactions.Indigo.dllの参照を削除
  2. ch03\SepCtp\ControlsExamples\Propertiesフォルダを丸ごとch03\NovCtp\ControlsExamplesにコピーする

コマンドプロンプトからサンプルを動かしている人向け
サンプルはDebug.WriteLineを使っているので、このままだと標準出力に何も表示されません。
MyApp.xaml.cs

using System;
using System.Windows;
using System.Data;
using System.Xml;
using System.Configuration;
// Traceクラスのため、追加
using System.Diagnostics;

namespace ControlsExamples
{
    /// <summary>
    /// Interaction logic for MyApp.xaml
    /// </summary>

    public partial class MyApp : Application
    {
        void AppStartingUp(object sender, StartupEventArgs e)
        {
            // Trace.Listenersに標準出力を追加
            TextWriterTraceListener myWriter = 
                new TextWriterTraceListener(System.Console.Out);
            Trace.Listeners.Add(myWriter);
            Window1 mainWindow = new Window1();
            mainWindow.Show();
        }

    }
}

Trace.Listenersにコンソールを追加。


ControlsExamples.csproj

<OutputType>exe</OutputType>

OutputTypeをwinexeからexeに変更。


ch03\NovCtp\ControlsExamples\Example19.xaml.cs

        private void AddRectangleClick(object sender, RoutedEventArgs e)
        {
            Rectangle rect = new Rectangle();
            SetShapeParams(rect);
            // inputBox.Selection.Start.InsertTextElement(new BlockUIContainer(rect));
            inputBox.Selection.Start.InsertTextElement(new InlineUIContainer(rect));
        }

        private void AddEllipseClick(object sender, RoutedEventArgs e)
        {
            Ellipse ellipse = new Ellipse();
            SetShapeParams(ellipse);
            // inputBox.Selection.Start.InsertTextElement(new BlockUIContainer(ellipse));
            inputBox.Selection.Start.InsertTextElement(new InlineUIContainer(ellipse));
        }

上記のように書き換えないと例外が発生します。


P.9 例1-11

×StartingUp="AppStartingUp"
○Startup="AppStartingUp"


P.10 例1-13

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.CSharp.targets(147,9): error MSB3105: 項目 "C:\Home\Projects\avalon\obj\Debug\MyApp.g.cs" は "Sources" パラメータで 1 度以上指定されました。重複した項目は "Sources" パラメータではサポートされていません。

というエラーがでます。

   <Page Include="MyApp.xaml" >

この部分が不要です。最初、原因が分からなくてWinFXを入れ直してしまいました。(^^;


P.40〜41

上部または下部にドッキングする項目の高さをDockPanelがどう決めるのか疑問に思うかも知れません。

上下にドッキングすると、DockPanelは項目を縦方向に引き伸ばし、使用可能な領域を満たします。

Top、Bottomにドッキングする例なので横方向だと思います。


P.66 表2-3

要素の名前 説明
AccessKey アクセラレータキーのスタイル部分に下線を引く

AccessKeyではなく、AccessTextですね。


P.77

30度の回転を適用した境界ボックスを表示しています。

30度ではなく50度ですね。


P.89

デバッグの出力

PreviewButtonDownButton
PreviewButtonDownGrid
PreviewButtonDownCanvas
PreviewButtonDownEllipse
ButtonDownEllipse
ButtonDownCanvas
ButtonDownGrid
ButtonDownButton

となっていますが、最後のButtonDownButtonは発生しません。Clickイベントは発生しますので、ボタンコントロールでは低レベルなイベントが抑制されていると思われます。


P.99〜100 例3-9

<Window x:Class="ControlsExamples.Example7"
    xmlns:m="urn:mylib"

と、xmlns:m="urn:mylib"の部分も入れておかないと、分かり難いと思います。


P.100 コマンドの有効化

メニューアイテムを呼び出すとQueryEnabledイベントが発生し、コマンドが無効化されていた場合はコマンドの実行が回避されます。

回避されません。少なくともTextBoxのCopyコマンドは駄目でした。


P.106

× AcceptReturnをTrueに
○ AcceptsReturnをTrueに


P.111〜P.112

× AccessKey
○ AccessText


P.134 図4-9

2つ目のTextBoxのBinding PathはNameではなくAgeですね。


P.138 例4-17

// 気をつけて!25からは下り坂です...

ソースコードからすると、「気をつけて!25を越えると下り坂です...」な気がします。どーでもいい話ですが。(^^;


P.140〜141 例4-20

Peopleオブジェクトの例なので正しくは、こうじゃないかしら。

<!-- Window1.xaml -->
<?Mapping XmlNamespace="XmlPersonBinding" ClrNamespace="PersonBinding" ?>
<Window x:Class="PersonBinding.Window1"
    ...
    xmlns:l="XmlPersonBinding"
    Title="PersonBinding">
  <Window.Resources>
    <l:AgeToForegroundConverter x:Key="AgeToForegroundConverter" />
    <l:People x:Key="Family">
      <l:Person Name="Tom" Age="9" />
      <l:Person Name="John" Age="11" />
      <l:Person Name="Melissa" Age="36" />
    </l:People>
    <DataTemplate DataType="{x:Type l:Person}">
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Path=Name}" />
        <TextBlock Text=" (age: " />
        <TextBlock Text="{Binding Path=Age}" 
        Foreground="{Binding Path=Age, 
        Converter={StaticResource AgeToForegroundConverter}}" />
        <TextBlock Text=")" />
      </StackPanel>
    </DataTemplate>
  </Window.Resources>
  <Grid DataContext="{StaticResource Family}">
    ...
  </Grid>
</Window>

書籍上の例は、XmlDataProviderを使ったもののようです。リストデータへのバインディングのサンプルなので、それがオブジェクトのコレクションであろうと、XMLで表記されていようと本質的に変わらないのに、なんで例を変えたのかしら。しかも、本文ではそのことにふれていません。


P.144 例4-24

重要な部分がごっそり消えてますね。ここまで間違っているのは初めてです。4章はミスが多い気がします。

<?Mapping XmlNamespace="XmlPersonBinding" ClrNamespace="PersonBinding" ?>
<Window ... Title="PersonBinding">
  <Window.Resources>
    <l:AgeToForegroundConverter x:Key="AgeToForegroundConverter" />
    ...
    </XmlDataProvider>
  </Window.Resources>
  <Grid DataContext="{StaticResource Family}">
    ...
    <ListBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding}" 
    IsSynchronizedWithCurrentItem="True" Margin="5" >
    ...
    </ListBox>
    <TextBlock ...>Name:</TextBlock>
    <TextBox Text= "{Binding XPath=@Name}" 
      Grid.Row="1" Grid.Column="1" Margin="5" />
    <TextBlock ...>Age:</TextBlock> <TextBox Text="{Binding XPath=@Age}" 
    Foreground= "{Binding XPath=@Age, 
      Converter={StaticResource AgeToForegroundConverter}}" 
    Grid.Row="2" Grid.Column="1" Margin="5" />
    ...
  </Grid>
</Window>

多分、こんな感じでしょう。


P.158

family.xmlファイルを指す相対URL

そんな記述例4-40には無いと思うのですが・・・

<XmlDataProvider x:Key="Family" Source="family.xml" XPath="/Family/Person" /> 

ここでは、XmlDataProviderはこのように記述しておくべきだと思います。