2012年8月30日木曜日

PCで

DVD 見れなくなとか。デフォルトで。

http://ascii.jp/elem/000/000/721/721780/

本機(MacBookAir)も DVD ドライブついてないし。
需要がなくなるから全体的にそっちに傾倒していきそうね。

2012年8月27日月曜日

[C#][WPF][Siliverlight] 地図上のアイコンをDrag & Drop

とりあえずコードをはっつける。






        <ListBox Name="map" SelectionChanged="map_SelectionChanged" Grid.Row="1">
            <ListBox.Resources>
                <Style TargetType="ListBoxItem">
                    <Setter Property="Canvas.Top" Value="{Binding Path=Top}"/>
                    <Setter Property="Canvas.Left" Value="{Binding Path=Left}"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ListBoxItem">
                                <Border MouseLeftButtonDown="item_MouseLeftButtonDown" 
                                        MouseLeftButtonUp="item_MouseLeftButtonUp" 
                                        MouseMove="item_MouseMove">
                                    <Image Source="{Binding Path=ImageSource}" Stretch="Uniform" />
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.Resources>
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas />
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListBox>



    public class Entity : INotifyPropertyChanged
    {
        private double top;
        public double Top
        {
            get { return top; }
            set
            {
                top = value;
                OnPropertyChanged("Top");
            }
        }
        private double left;
        public double Left
        {
            get { return left; }
            set
            {
                left = value;
                OnPropertyChanged("Left");
            }
        }
        public BitmapImage ImageSource { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
    }




        private bool moving = false;
        private Entity selectedItem = null;
        private Point offset;

        public Page()
        {
            InitializeComponent();

            // アイコン情報のリストを作ってね
            map.ItemsSource = new List<Entity>();
        }


        private void item_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.moving = true;
            Border control = sender as Border;
            if (control != null)
            {
                this.offset = e.GetPosition(control);
            }
        }

        private void item_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            this.moving = false;
        }

        private void item_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.moving && this.selectedItem != null)
            {
                Point position = e.GetPosition(map);
                this.selectedItem.Left = position.X - this.offset.X;
                this.selectedItem.Top = position.Y - this.offset.Y;
            }
        }

        private void map_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.selectedItem = map.SelectedValue as Entity;
            controlPanel.DataContext = this.selectedItem;
        }




ドラッグ&ドロップはおまけみたいなもん。
レイアウトを XAML でごりごりデザインするより ListBox つかうとシンプルでかなりすっきりする。こういう斬新なのがすきだ。



[C#][WPF][Siliverlight] XAML をロード


する話。

経緯についてうだうだ書いているが、面倒な人は下の方にコードを書いているので飛ばしてね。

既存アプリケーションの MVVM 化を目指しているんだけど、イベントドリブンでの開発しか知らない人たちを説得するのはなんとも骨が折れる話である。
勉強しようぜ。

いつも画面デザインはデザイナーの人にお願いして PNG ファイルもしくは PSD ファイルを提供してもらってたけど、とりあえず XAML で提供してもらえそうなところまでもっていけた。まぁ PSD を Blend でインポートすればいいだけかもしれんが。

そのまま使ってもいんだけど、現場で微調整出来るようにするには提供してもらった XAML をビルドするのではなくコンテンツそして動的にロードできるようにしなければならない。

ぽいっと読めればいんだけど、デザインさんから提供されるものは、CS ファイルがついている。つまりコードビハインドなので XAML ファイルを直接ロードすることはできない。

色々試してみたけど、どうやら x:Class タグがあるとコードビハインドだと認識されるっぽいな。こいつをスキップすればロードしてインスタンスを生成することが出来た。ちょっと強引だけど。こんな感じ。



            XamlSchemaContext xamlContext = System.Windows.Markup.XamlReader.GetWpfSchemaContext();
            XmlReader xmlReader = XmlReader.Create("test.xaml");
            XamlXmlReader xamlReader = new XamlXmlReader(xmlReader, xamlContext);
            XamlObjectWriter writer = new XamlObjectWriter(xamlReader.SchemaContext);
            while (!xamlReader.IsEof)
            {
                if (xamlReader.Member != null && (xamlReader.Member.Name == "Class")
                {
                    xamlReader.Skip();
                }
                else
                {
                    writer.WriteNode(xamlReader);
                    xamlReader.Read();
                }
            }

            UserControl control = writer.Result as UserControl;


[2012.11.08 追記]
Silverlight だとこのやり方は出来ないので、テキストファイルとして読み込んで、x:Classを正規表現で読飛ばすしかないのかな。



            using (var stream = File.OpenRead(file))
            {
                var reader = new StreamReader(stream);
                var xaml = reader.ReadToEnd();

                // 正規表現でClass属性を読み飛ばす
                Regex regex = new Regex("x:Class.*?\"\r\n");
                xaml = regex.Replace(xaml, "\r\n");

                var control = XamlReader.Load(xaml) as UserControl;
            }




x:Classから改行位置までを読飛ばしているので、その間にnamespaceとか記述しているとアウトですが。。。



2012年8月8日水曜日

今日は品川で

サーバー仮想化の検証。
待ち合わせよりかなり早くついてしまった。
それにしてもものすごい人の数。
今日は涼しい。

2012年8月7日火曜日

[C#]文字列からインスタンス生成

DLL を動的にロードしてインスタンスを文字列で指定したクラスのインスタンスを生成する。

            Assembly assembly = Assembly.LoadFrom(dllName);
            Module module = assembly.GetModule(dllName);
            Type type = module.GetType(className);
            var instance = Activator.CreateInstance(type);

クラス名は Namespace + Class 。

[C#]文字列から Type 生成

            Assembly assembly = Assembly.GetExecutingAssembly();

            string typeName = "Namespace + ClassName";
            Type type = assembly.GetType(typeName, false, true);

異なるアセンブリの型を取得する場合は、そのアセンブリ内の適当なクラスの typeof().Assembly とかを使う。





[VMware Fusion]Ctrl + Click

Windows でコントロールキーを押しながらクリックすると、複数選択したり選択を解除できたりする。

しかし、Mac 上の仮想 OS として動作している Windows でコントロールキーを押しながらクリックすると、コンテキストメニューが表示される。つまり右クリックと同様の振る舞いとなる。




これは Mac のショートカットキーが優先されている為である。




Mac ではコントロールキー+クリックで右クリックの効果が得られる。
私にとってそれは昔、

「Mac って右クリックないんでしょ」
「何言ってんの!? Control キー押しながらクリックしたらいーんだよ」

っていう負け惜しみを言う為の機能だったのだが(笑)、これの影響で Windows 上での振る舞いが変わってしまっていた。




回避方法だが、

VMware Fusion - 環境設定 -  キーボードとマウス - マウスショートカット


の、副ボタンのチェックを外せば OK。