2013年3月22日金曜日

[Silverlight]XAMLにデータをXMLとして記述する

XML スキーマに合わせてカスタムコントロールを用意すればある程度出来るが、つまづいたのは List<T> 型。XAML からの定義がうまくいかなかったりする。回避するには List<T> を継承したクラスでワンクッション置く必要がある。

以下に数値キーに対するイメージのカスタムコントロールを記述する。


    public class SampleContentControl : ContentControl
    {
        public ImageList ImageList
        {
            get { return (ImageList)GetValue(ImageListProperty); }
            set { SetValue(ImageListProperty, value); }
        }

        public static readonly DependencyProperty ImageListProperty =
            DependencyProperty.Register("ImageList", typeof(ImageList), typeof(SampleContentControl), new PropertyMetadata(new ImageList()));
    }

    public class ImageList : List<ImageInfo>
    {
    }

    public class ImageInfo
    {
        public int Key { get; set; }
        public ImageSource Value { get; set; }
    }




XAML 側の定義はこうなる。(ResourceDicitonary内ね)


    <local:ImageList x:Key="imageList">
        <local:ImageInfo Key="1" Value="{StaticResource aaa}"/>
        <local:ImageInfo Key="2" Value="{StaticResource bbb}"/>
        <local:ImageInfo Key="3" Value="{StaticResource ccc}"/>
    </local:ImageList>




[C#]画像の印刷ダイアログをプロセス起動する

Windows 7 の場合、画像ファイルを指定してプロセス起動すると、Windows フォトビューアーが起動する(はず)。


            Process.Start(@"D:\penguins.jpg");


でも出したいのは印刷プレビュー画面。画像ファイルを右クリック->印刷で選んだ時のダイアログ。こんなやつ。



レジストリとか色々調べてしまったが(それはそれで勉強になった)、プロセス起動時にVerbプロパティに print を指定してあげるといい。

            ProcessStartInfo info = new ProcessStartInfo(@"D:\penguins.jpg");
            info.Verb = "print";
            Process.Start(info);


Windows フォトビューアーをコマンド起動


%SystemRoot%\System32\rundll32.exe "%ProgramFiles%\Windows Photo Viewer\PhotoViewer.dll", ImageView_Fullscreen 画像ファイル名






[WPF]Listアイテムのコンテキストメニューのコマンドバインディング(MVVM)

DataGrid でも ListView でも ListBox でも当てはまると思うけど、行を右クリックしてViewModel に記述されたコマンドをキックするにはちょっとコツが必要。

普通にバインドさせると、ListItem の ViewModel にバインドしようとしてしまうからみたい。

わかってしまえば簡単。
Windowまで遡れば、DataContext に ViewModel が入ってるんで、コマンドまで辿れる。


    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>


            <ContextMenu x:Key="execMenu">
                <MenuItem Header="実行"  Command="{Binding Path=DataContext.ExecuteCommand, 
                                                                             RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/>
            </ContextMenu>

[Silverlight]ResourceDictionary 分離

ResourceDictionary を複数ファイルに分割して、片方のリソースから片方のリソースへの参照があると、XamlParseException が発生して起動出来ない。

-----------------
XamlParseException
Name/Key XXXXXX を持つ Resource が見つかりません [Line: XX Position: XX]

-----------------


Expression Blend Preview For Silverlight 5 だからなのかもしれないが、App.xaml の MergedDictionaries 内で複数のリソースファイルをロードしようとした時に別リソースファイルへの参照があるとダメそう。イメージファイルの定義が1ファイルに纏めたいんだけど。。。

対処としては、App.xaml 内で定義している ResourceDictionary をコードビハインドでロードさせる。


        private void loadResource(Uri uri)
        {
            var info = Application.GetResourceStream(uri);
            string xaml;
            using (var reader = new StreamReader(info.Stream))
            {
                xaml = reader.ReadToEnd();
            }

            ResourceDictionary result = (ResourceDictionary)XamlReader.Load(xaml);
            foreach (DictionaryEntry item in result)
            {
                
                try
                {
                    Application.Current.Resources.Add(item.Key, item.Value);
                }
                catch (Exception ex)
                {
                }
            }
        }




実行時はそれでいんだけど、デザイナで表示出来ないのもなんとかならんか。調べてみると、DesignTimeResources.xaml というものがあり、Blend 起動時に参照が切れているリソースがあると、自動生成してくれる。(Properties ディレクトリ配下出来る)

これでもダメな場合、複数の ResourceDictionary ファイルを1ファイル内でロードするようにしたものをDesignTimeResources.xamlに書くとよい。

それでもダメな場合、一度ビルドして Blend ないし VisualStudio を終了させ、起動させると表示されることがある。

定義の仕方が悪いのかもしれないが、なんともすっきりしないやり方だ〜。

[jQuery]iframeのスムーズな切換え

最近ではあまり使われなくなっている Frame 関係だけど、業務アプリケーションではまだまだ使っていることも多い。

iframe のコンテンツを切り替える際に iframe 内が真っ白になってしまう。
切換え先のページのロードが重たければ、白い画面がしばらく表示されることになるのだが、なんとかならんか〜と考えてみた。

結論から言うと、iframe  を div タグ内に入れて、div タグをフェードイン/フェードアウトさせればフワフワっとページを切り替えることが出来る。

フェードインは iframe の loaded イベントで行う。


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript" language="javascript" src="jquery-1.9.0.min.js"></script>
    <script type="text/javascript" language="javascript">
var index = 0;
var pages = new Array("aaaa.html", "bbbb.html");
function frameChange(){
    $('#contents').animate({ opacity: 0 }, 500, function () {
        $('#contents').css("visibility", "hidden");
        main.location.href = pages[index];
        index++;
        index = index % 2;
    });
}
function loaded(){
    $('#contents').css("visibility", "visible");
    $('#contents').animate({ opacity: '1' }, 800, function () {

    });
}
    </script>
</head>
<body style="background-color:Black;">
<input type="button" value="切替" onclick="frameChange()">
    <div id="contents">
        <iframe name="main" id="main" scrolling="no" onload="loaded();"/>
    </div>
</body>
</html>


[jQuery]アコーディオンメニュー

dtタグを使ってメニューを作成し、サブメニューは sideToggle によるアニメーションでのの表示/非表示を切り替えることでアコーディオン風のメニューが出来上がる。


<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript" language="javascript" src="jquery-1.9.0.min.js"></script>
    <script type="text/javascript" language="javascript">
$(document).ready(function(){
    $('dd').css("display", "none");
    $("dt").click(function () {
        if ($(this).next().children(0).children().length != 0) {
            $(this).next().slideToggle("slow");
        }
        return false;
    });
});
    </script>
</head>
<body>
<dt>メニュー1</dt>
<dd>
<ul>
<li>サブメニュー1</li>
<li>サブメニュー2</li>
<li>サブメニュー3</li>
</ul>
</dd>
<dt>メニュー2</dt>
<dd>
<ul>
<li>サブメニュー1</li>
<li>サブメニュー2</li>
<li>サブメニュー3</li>
</ul>
</dd>
</body>
</html>



[C#]FlagBooleanConverter

DBはBoolean型がなくて、0か1で意味を持たせることが多々あるんで、直接 bool 型として扱えるよう、Converter を作った。スニペット的に貼付けておく。


    public class FlagBooleanConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int param;
            if (!int.TryParse(value.ToString(), out param))
            {
                return DependencyProperty.UnsetValue;
            }

            return param.Equals(1);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            bool param;
            if (!bool.TryParse(value.ToString(), out param))
            {
                return DependencyProperty.UnsetValue;
            }
            
            return param ? 1 : 0;
        }
    }


[Silverlight]トグルスイッチボタン

ON/OFFボタンを作ってみた。
イメージはこんな感じ。


クリックすると黒い境界が動いてON<->OFFが切り替わる。

Template内にサイズを持たせているので微妙なんだけどねぇ。
XAMLを貼付けておく。


<ControlTemplate x:Key="ToggleSwitchControlTemplate" TargetType="ToggleButton">
<Grid Height="22">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.2" To="Checked"/>
<VisualTransition GeneratedDuration="0:0:0.2" To="Unchecked"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Checked"/>
<VisualState x:Name="Unchecked">
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" To="-45" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)" Storyboard.TargetName="grid" d:IsOptimized="True">
                                <DoubleAnimation.EasingFunction>
                                    <CircleEase EasingMode="EaseIn"/>
                                </DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</VisualState>
<VisualState x:Name="Indeterminate"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Canvas>
<Canvas.Clip>
<RectangleGeometry Rect="0,0,55,22" />
</Canvas.Clip>
<Grid x:Name="grid" Height="22" Width="100" RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<CompositeTransform TranslateX="0"/>
</Grid.RenderTransform>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="45"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="45"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Background="White" BorderThickness="2,2,0,2" BorderBrush="Gray">
<Border Margin="2,2,0,2" Background="#FF41B1E1">
<TextBlock Text="ON" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Foreground="White"/>
</Border>
</Border>
<Border Grid.Column="1" Background="Black"/>
<Border Grid.Column="2" Background="White"  BorderThickness="0,2,2,2" BorderBrush="Gray">
<Border Margin="0,2,2,2" Background="Gray">
<TextBlock Text="OFF" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" Foreground="White"/>
</Border>
</Border>
</Grid>
</Canvas>
</Grid>
</ControlTemplate>


2013年3月19日火曜日

朝田氏の

警鐘はとても重要。



From 医龍 vol.20


蛇口は常に空いている。
栓は無い。
維持するなら新しいものを取り込み続けるしかない。


四十肩は恐らく技術力のことも指す。
腕が上がらなくなることへの準備が必要だ。