かずきのBlog

C#やJavaやRubyとメモ書き

目次

Blog 利用状況

ニュース

わんくまBlogが不安定になったため、前に書いてたはてなダイアリーにメインを移動します。
かずきのBlog@Hatena
技術的なネタは、こちらにも、はてなへのリンクという形で掲載しますが、雑多ネタははてなダイアリーだけに掲載することが多いと思います。
コメント
プログラマ的自己紹介
お気に入りのツール/IDE
プロフィール
経歴
広告
アクセサリ

書庫

日記カテゴリ

[WPF][C#]WPFでAccessチックなリサイズ可能コンボボックスを作ってみよう その2

かな~り昔に、コンボボックスのドロップダウンがリサイズ可能なコントロールをUserControlを使って作った。
との時のエントリはこちら

あまりにも手抜きチックだったので、ちょびっと時間をとってそれっぽいのを作ってみた。
ただ、それでも本物のComboBoxに比べると見た目が微妙に劣ってる。細かいところまで合わせようとすると非常に骨が折れるので今回のも妥協の塊であることを最初に断っておきますorz

コントロールの名前は、MyComboBoxにしてComboBoxを継承して作ってる。
追加したプロパティは、ドロップダウンの幅と高さのためのプロパティを2つ。後は、ActualWidthが変更されたときのドロップダウンの幅も変更されるような仕組みと、Thumbのドラッグイベントに応答してドロップダウンの幅と高さを変えるコードを仕込んだ。

後はXAML側でPopupの幅と高さをドロップダウンの幅と高さのプロパティにバインドしてやればOKという寸法です。

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace CustomComboBox
{
    /// <summary>
    /// ドロップダウンのサイズをマウスで変更可能なコンボボックス
    /// </summary>
    public class MyComboBox : ComboBox
    {

        #region DropDownの幅
        public double DropDownWidth
        {
            get { return (double)GetValue(DropDownWidthProperty); }
            set { SetValue(DropDownWidthProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DropDownWidth.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DropDownWidthProperty =
            DependencyProperty.Register("DropDownWidth",
                typeof(double),
                typeof(MyComboBox),
                new UIPropertyMetadata(0.0,
                    (sender, e) => { },
                    (sender, value) => 
                    {
                        // ドロップダウンの幅はActualWidthより小さくしないようにしてみた
                        double v = (double)value;
                        double actualWidth = (double)sender.GetValue(FrameworkElement.ActualWidthProperty);
                        return Math.Max(actualWidth, v);
                    }));
        #endregion


        #region DropDownの高さ(悔しいけどデフォルト150で固定)
        public double DropDownHeight
        {
            get { return (double)GetValue(DropDownHeightProperty); }
            set { SetValue(DropDownHeightProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DropDownHeight.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DropDownHeightProperty =
            DependencyProperty.Register("DropDownHeight",
                typeof(double),
                typeof(MyComboBox),
                new UIPropertyMetadata(150.0,
                    (sender, e) => { },
                    (sender, e) =>
                    {
                        // 高さは16以下にならないようにしてみた
                        double value = (double)e;
                        return Math.Max(value, 16.0);
                    }));
        #endregion


        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == FrameworkElement.ActualWidthProperty)
            {
                // ActualWidthが変更されたら、DropDownWidthのプロパティの値も変更する。
                this.CoerceValue(DropDownWidthProperty);
            }
        }

        static MyComboBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MyComboBox), new FrameworkPropertyMetadata(typeof(MyComboBox)));
        }

        public MyComboBox()
        {
            // ドラッグのイベントを登録
            AddHandler(Thumb.DragDeltaEvent, new DragDeltaEventHandler(Thumb_DragDelta));
        }

        private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            // ドラッグで移動したぶんだけ、ドロップダウンのサイズを変更する
            DropDownWidth += e.HorizontalChange;
            DropDownHeight += e.VerticalChange;
        }
    }
}

そして、Generic.xamlにComboBoxのテンプレートの劣化版みたいなものをゴリゴリと書いていった。

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:CustomComboBox">


    <Style TargetType="{x:Type local:MyComboBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:MyComboBox}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <StackPanel>
                            <Grid Name="editorHolder">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition />
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <ContentPresenter Name="ContentHolder" 
                                                  Grid.Row="0" Grid.Column="0" 
                                                  VerticalAlignment="Center"
                                                  Content="{TemplateBinding SelectedValue}"
                                                  ContentTemplate="{TemplateBinding ItemTemplate}"
                                                  ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>
                                <TextBox Name="ContentEditor" 
                                         Grid.Row="0" Grid.Column="0"
                                         Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedValue}" 
                                         Visibility="Hidden"/>
                                <ToggleButton Grid.Row="0" Grid.Column="1" 
                                              ClickMode="Press"
                                              IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsDropDownOpen}">
                                    <Polygon Points="0,0 6,0 3,6" Fill="Black" 
                                             Margin="5"/>
                                </ToggleButton>
                            </Grid>
                            <Popup IsOpen="{TemplateBinding IsDropDownOpen}"
                                   Width="{TemplateBinding DropDownWidth}"
                                   Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DropDownHeight}">
                                <Border Background="White" 
                                        BorderBrush="Black" 
                                        BorderThickness="1">
                                    <DockPanel>
                                        <Thumb DockPanel.Dock="Bottom" 
                                               HorizontalAlignment="Right" 
                                               VerticalAlignment="Bottom" 
                                               Width="15"
                                               Height="15" />
                                        <ScrollViewer HorizontalScrollBarVisibility="Auto"
                                                      VerticalScrollBarVisibility="Auto">
                                            <StackPanel IsItemsHost="True" />
                                        </ScrollViewer>
                                    </DockPanel>
                                </Border>
                            </Popup>
                        </StackPanel>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEditable" Value="True">
                            <Setter TargetName="ContentHolder" Property="Visibility" Value="Hidden" />
                            <Setter TargetName="ContentEditor" Property="Visibility" Value="Visible" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

このBlog的に珍しいのは、Triggerを使ってIsEditableの値に応じて表示するコントロールを切り替えてるのくらいかな?後は単純に物を置いていってます。

動作

出来上がったMyComboBoxをWindowにおいてみた。Window1.xamlは↓のような感じ。いつもどおりのPersonクラスも定義してある。

<Window x:Class="CustomComboBox.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:CustomComboBox"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <x:Array x:Key="people" Type="{x:Type local:Person}">
            <local:Person Name="田中 太郎" />
            <local:Person Name="田中 次郎" />
            <local:Person Name="田中 三郎" />
            <local:Person Name="田中 四郎" />
            <local:Person Name="田中 五郎" />
            <local:Person Name="田中 六郎" />
            <local:Person Name="田中 七郎" />
            <local:Person Name="田中 八郎" />
            <local:Person Name="田中 九郎" />
            <local:Person Name="田中 十郎" />
            <local:Person Name="じゅげむじゅげむ ごこうのすりきれ かいじゃりすいぎょのすいぎょうまつうんらいまつふうらいまつ くうねるところにすむところやぶらこうじのぶらこうじ ぱいぽぱいぽぱいぽのしゅーりんがん しゅーりんがんのぐーりんだい ぐーりんだいのぽんぽこぴーのぽんぽこなーのちょうきゅうめいのちょうすけ" />
        </x:Array>
        <DataTemplate x:Key="personDataTemplate" DataType="{x:Type local:Person}">
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
    </Window.Resources>
    <StackPanel>
        <local:MyComboBox ItemsSource="{StaticResource people}"
                          ItemTemplate="{StaticResource personDataTemplate}"/>
    </StackPanel>
</Window>

これを実行してドロップダウンを表示させてみると最初は↓のような感じで出てくる。
image

右下のThumbをつまんでドラッグするとサイズ変更もばっちりできてる。
image

因みに、うちのディスプレイでは、最大までドロップダウンの幅を広げても「じゅげむじゅげむ…ちょうすけ」さんの名前は表示しきれませんでした。
image

このプロジェクトの全体のダウンロードはこちらから。

投稿日時 : 2008年9月7日 12:05

Feedback

# cheap supra shoes 2012/12/08 13:36 http://supratkstore.webs.com/

Its great as your other articles : D, thanks for posting . "If Christ were here now there is one thing he would not be--a christian." by Mark Twain.

# longchamp acheter 2012/12/14 20:43 http://www.saclongchampachete.info/category/longch

Great blog post, it's invaluable information.

# longchamp le pliage 2012/12/15 16:21 http://www.soldesacslongchamp.info/category/sacs-l

gripping revenues of observations bursting away from your photos.

# burberry uk 2012/12/15 23:01 http://www.burberryuksale.info/category/handbags-b

You definitely know your own stuff...

# le pliage longchamps tote 2012/12/16 17:57 http://www.sacslongchamp2012.info/le-pliage-longch

Now i'm impressed by the products information for this website. There are plenty of good resources here.

# bags burberry 2012/12/17 2:54 http://www.burberryuksale.org/category/bags-burber

I guess I'm not the only one having all the enjoyment in this case!

# トリーバーチ店舗安い 2012/12/17 22:03 http://www.torybruchjp.info/category/トリーバーチ-店舗

we re-watched god, the father of all the Rings trilogy, the Godfather trilogy, and related to twenty several other movies we loved together with hadn¡¯t watched in a while.

# sac2012femmes.wordpress.com 2012/12/18 2:11 http://sac2012femmes.wordpress.com

gripping waters of comments bursting through the photos.

# sacs Burberry 2012/12/19 14:13 http://sacburberrysoldesfr.webnode.fr/actualites

I have not looked in to Sennheisers as well as am hunting for new tote.

# michael kors sac 2012/12/22 18:58 http://sacmichaelkorssoldes.monwebeden.fr/#/bienve

I be aware of everybody will hate in it, but I don't even think they glimpse so damaging.

# chine destock 2013/01/08 7:12 http://www.destockchinefr.fr/jeans-marque-pas-cher

Don‘s fritter away it slow on your wow/lady,which isn‘s prepared fritter away their very own duration on you.
chine destock http://www.destockchinefr.fr/jeans-marque-pas-cher/

# ckgucci 2013/01/11 11:08 http://www.robenuk.eu/

If you should are going to choosing the best hidden knowledge by means of an opponent, describe to this by way of the someone.
ckgucci http://www.robenuk.eu/

# http://www.destockchinefr.fr/maillot-de-club-pas-cher/serie-a-pas-cher/ 2013/01/13 4:51 http://www.destockchinefr.fr/maillot-de-club-pas-c

In no way frown, even though you could be dismal, while you can't predict who is decreasing gets interested a person's teeth.
http://www.destockchinefr.fr/maillot-de-club-pas-cher/serie-a-pas-cher/ http://www.destockchinefr.fr/maillot-de-club-pas-cher/serie-a-pas-cher/

# generic clomiphene https://clomidt.com
clomid treats 2022/01/03 19:20 Clomid

generic clomiphene https://clomidt.com
clomid treats

# anti fungal pills without prescription: https://medrxfast.com/ 2022/08/07 8:50 MedsRxFast

anti fungal pills without prescription: https://medrxfast.com/

# Read here. Everything what you want to know about pills.
https://canadianfast.com/
Drug information. Medicament prescribing information. 2023/02/20 0:24 CanadaBest

Read here. Everything what you want to know about pills.
https://canadianfast.com/
Drug information. Medicament prescribing information.

# sildenafil without a doctor's prescription - https://cheapdr.top/# 2023/04/03 9:35 Dikolipo

sildenafil without a doctor's prescription - https://cheapdr.top/#

# walgreens sleep aids over the counter https://overthecounter.pro/# 2023/05/09 0:35 OtcJikoliuj

walgreens sleep aids over the counter https://overthecounter.pro/#

# reputable indian pharmacies https://indiapharmfd.com/# - top 10 pharmacies in india 2023/06/08 8:42 IndiaPharm

reputable indian pharmacies https://indiapharmfd.com/# - top 10 pharmacies in india

タイトル
名前
Url
コメント