Pertanyaan pengikatan Template Kontrol Kustom

Bayangkan seorang desainer formulir dengan hamparan kisi yang mewakili koordinat pada bidang. Saya mencoba mengikat properti hamparan kisi ke Canvas dalam ItemsControl khusus.

Grid dibuat menggunakan VisualBrush. Viewbox dan Viewport VisualBrush terikat ke Rect dalam kode, begitu pula Height dan Width dari Rectangle yang digunakan untuk menampilkan petak petak. Namun, saat kontrol ditampilkan, petak petak tampak "sangat kecil" (kisi hanya berwarna abu-abu) sehingga jika saya memperbesar petak, program pada akhirnya akan terhenti, tidak dapat merendernya. Jelas, ini bukanlah efek yang saya inginkan.

<Style TargetType="{x:Type Controls:FormControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Controls:FormControl}">
                <Border Background="White"
                        BorderBrush="Black"
                        BorderThickness="1"
                        Padding="49">
                    <Grid Height="{TemplateBinding CanvasHeight}"
                          Width="{TemplateBinding CanvasWidth}">
                        <Grid.Background>
                            <!--"0,0,6,11.3266666666667"-->
                            <VisualBrush TileMode="Tile"
                                         Viewbox="{TemplateBinding GridUnitViewbox}"
                                         ViewboxUnits="Absolute"
                                         Viewport="{TemplateBinding GridUnitViewbox}"
                                         ViewportUnits="Absolute">
                                <VisualBrush.Visual>
                                    <Rectangle Height="{Binding RelativeSource={RelativeSource TemplatedParent},Path=GridUnitViewbox.Height}"
                                               HorizontalAlignment="Left"
                                               Opacity="{TemplateBinding GridOpacity}"
                                               Stroke="Black"
                                               StrokeThickness=".1"
                                               VerticalAlignment="Top"
                                               Width="{Binding RelativeSource={RelativeSource TemplatedParent},Path=GridUnitViewbox.Width}" />
                                </VisualBrush.Visual>
                            </VisualBrush>
                        </Grid.Background>
                        <ItemsPresenter />
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="Controls:FormControlItem">
                <Setter Property="Canvas.Left"
                        Value="{Binding Path=X}" />
                <Setter Property="Canvas.Top"
                        Value="{Binding Path=Y}" />
            </Style>
        </Setter.Value>
    </Setter>
</Style>

Tahu apa yang saya lakukan salah di sini. Terima kasih.

EDIT: Mungkin sedikit lebih banyak latar belakang tentang apa yang saya lakukan dapat menempatkannya dalam konteks yang lebih baik. Saya bekerja di sebuah perusahaan perangkat lunak persiapan pajak dan, saat ini, divisi formulir kami membuat formulir pengganti menggunakan markup yang ditulis untuk produk kami sekitar satu juta tahun yang lalu. Agak rumit membuat formulir dengan cara ini, jadi saya mengembangkan visual "Perancang Formulir" untuk mereka yang akan lebih mirip WYSIWYG dan menerjemahkan konten desainer ke dalam markup. Ya, IRS benar-benar anal tentang segala sesuatu di formulir yang PERSIS dengan aslinya, jadi ada standar yang sangat longgar di mana "hamparan kotak" dapat ditempatkan di atas formulir untuk menentukan ke mana segala sesuatunya harus pergi; pada dasarnya semacam bidang koordinat.

FormControl pada dasarnya adalah representasi visual dari salah satu bentuk pengganti yang akan dibuat oleh salah satu desainer bentuk.

CanvasWidth dan CanvasHeight adalah pembungkus CLR untuk Properti Ketergantungan. Mereka diberi nilai dalam OnApplyTemplate() dengan mengalikan dimensi GridUnitViewbox dengan berapa banyak petak petak yang diperlukan dalam hamparan petak, yaitu. grid 78x63 dalam banyak kasus.

Nama CanvasWidth dan CanvasHeight menurut saya mungkin sedikit menyesatkan karena tidak mengacu pada kontrol Canvas, tetapi pada Grid yang menampung Canvas (mungkin perlu mengubah konvensi penamaan). Artinya, CanvasHeight, CanvasWidth dan GridUnitViewbox tidak bergantung pada properti kontrol apa pun, melainkan penghitungan yang dilakukan di OnApplyTemplate().

    public static readonly DependencyProperty GridUnitViewboxProperty =
        DependencyProperty.Register("GridUnitViewbox", typeof(Rect), typeof(FormControl),
        new FrameworkPropertyMetadata(new Rect(0, 0, 6, 11.3266666666667),
            FrameworkPropertyMetadataOptions.AffectsMeasure |
            FrameworkPropertyMetadataOptions.AffectsParentMeasure));

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        FormattedText formattedText = new FormattedText(
            "X",
            CultureInfo.GetCultureInfo("en-us"),
            FlowDirection.LeftToRight,
            new Typeface("Courier New"),
            10,
            Brushes.Black);

        this.GridUnitViewbox = new Rect(0, 0, formattedText.WidthIncludingTrailingWhitespace, formattedText.Height);

        if (this.PageLayout == PageLayoutType.Landscape)
        {
            this.CanvasHeight = this.GridUnitViewbox.Height * 48.0;
            this.CanvasWidth = this.GridUnitViewbox.Width * 109.0;
        }
        if (this.PageLayout == PageLayoutType.Portrait)
        {
            this.CanvasHeight = this.GridUnitViewbox.Height * 63.0;
            this.CanvasWidth = this.GridUnitViewbox.Width * 78.0;
        }
    }

Kontrol Grid sebenarnya melakukan apa yang saya inginkan. Ini adalah VisualBrush dan Rectangle di dalamnya yang tidak mengikat dengan benar atau tidak diperbarui dengan benar. Komentar tepat di bawah <Grid.Background> adalah nilai pengujian hard-code yang saya gunakan untuk dimensi VisualBrush Viewbox dan Viewport serta Rectangle sebelum saya sempat mengikat nilai dan menghasilkan, secara visual, persis seperti yang saya inginkan. Saya juga telah mengonfirmasi bahwa 6 dan 11.3266666666667 sebenarnya adalah nilai untuk dimensi GridUnitViewbox selama runtime.

Namun saya merasa pengikatannya menghasilkan '0,0,0,0', karena hamparan kisi hanyalah bayangan abu-abu yang menghabiskan banyak sumber daya; sebenarnya mengunci program jika Anda memperbesarnya. Seperti yang Anda lihat, dalam kode saya mencoba menambahkan AffectsMeasure dan AffectsParentMeasure ke opsi Metadata properti ketergantungan dengan harapan mungkin UI tidak diperbarui dengan benar setelah dimensi GridUnitViewbox diperbarui, tetapi saya salah. Saya tidak yakin apa lagi yang bisa terjadi.


person SirBeastalot    schedule 11.03.2011    source sumber
comment
Anda harus lebih spesifik dan menguraikan masalah Anda. Diragukan bahwa orang akan menghabiskan waktu untuk menelusuri sebagian besar markup XAML tersebut.   -  person Stephen Chung    schedule 11.03.2011


Jawaban (2)


Baiklah, kalau-kalau ada orang lain yang mengalami masalah serupa, saya menemukan solusinya. Rupanya VisualBrush sedikit rewel tentang TemplateBindings. Saya menyesuaikan XAML dan memecahkan masalah:

<VisualBrush TileMode="Tile"
             Viewbox="{Binding RelativeSource={RelativeSource TemplatedParent},Path=GridUnitViewbox}"
             ViewboxUnits="Absolute"
             Viewport="{Binding RelativeSource={RelativeSource TemplatedParent},Path=GridUnitViewbox}"
             ViewportUnits="Absolute">

Ini artikel tempat saya mendapatkan informasinya.

person SirBeastalot    schedule 11.03.2011

Apa itu CanvasWidth dan CanvasHeight? Apakah sudah terdefinisi?

Selain itu, saya yakin bahwa kanvas tidak memiliki ukuran kecuali ditentukan secara eksplisit. Saat Anda mengikatnya, lebar/tingginya mungkin nol.

Coba ActualWidth dan ActualHeight atau kanvas setelah proses rendering untuk melihat apakah keduanya mengandung nilai apa pun, tetapi afaiknya tidak kecuali Anda memberikannya.

person Stephen Chung    schedule 11.03.2011