คำถามเกี่ยวกับการผูกเทมเพลตการควบคุมแบบกำหนดเอง

ลองนึกภาพผู้ออกแบบฟอร์มที่มีการซ้อนทับตารางซึ่งจะแสดงพิกัดบนระนาบ ฉันกำลังพยายามผูกคุณสมบัติของตารางซ้อนทับกับ Canvas ภายใน ItemsControl ที่กำหนดเอง

ตารางถูกสร้างขึ้นโดยใช้ VisualBrush Viewbox และ Viewport ของ VisualBrush ถูกผูกไว้กับ Rect ในโค้ด เช่นเดียวกับ Height และ Width ของ Rectangle ที่ใช้เพื่อแสดงไทล์ตาราง อย่างไรก็ตาม เมื่อส่วนควบคุมแสดงขึ้น ไทล์กริดดูเหมือนจะ "เล็กมาก" (กริดเป็นเพียงสีเทา) โดยที่หากฉันซูมเข้าไปในกริด โปรแกรมก็จะขยายใหญ่ขึ้นจนไม่สามารถเรนเดอร์ได้ แน่นอนว่านี่ไม่ใช่ผลลัพธ์ที่ฉันต้องการ

<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>

มีความคิดว่าฉันทำอะไรผิดที่นี่ ขอบคุณ.

แก้ไข: บางทีพื้นหลังเพิ่มเติมเล็กน้อยของสิ่งที่ฉันทำอาจทำให้บริบทดีขึ้น ฉันทำงานให้กับบริษัทซอฟต์แวร์การเตรียมภาษี และในปัจจุบัน แผนกแบบฟอร์มของเราสร้างแบบฟอร์มทดแทนโดยใช้มาร์กอัปที่เขียนขึ้นสำหรับผลิตภัณฑ์ของเราเมื่อประมาณล้านปีก่อน การสร้างแบบฟอร์มด้วยวิธีนี้จะยุ่งยากเล็กน้อย ดังนั้นฉันจึงพัฒนา "ตัวออกแบบฟอร์ม" แบบภาพสำหรับพวกเขา ซึ่งจะเหมือนกับ WYSIWYG มากกว่า และแปลเนื้อหาของตัวออกแบบเป็นมาร์กอัป กรมสรรพากรเป็นผู้เชี่ยวชาญจริงๆ เกี่ยวกับทุกสิ่งที่อยู่ในแบบฟอร์มซึ่งตรงกับต้นฉบับ ดังนั้นจึงมีมาตรฐานที่หลวมมากซึ่งสามารถวาง "การซ้อนทับตาราง" ไว้เหนือแบบฟอร์มเพื่อกำหนดว่าสิ่งต่างๆ ต้องไปในจุดใด โดยพื้นฐานแล้วเป็นระนาบพิกัดอะไรสักอย่าง

FormControl โดยพื้นฐานแล้วคือการนำเสนอด้วยภาพของหนึ่งในแบบฟอร์มทดแทนเหล่านี้ที่หนึ่งในแบบฟอร์มที่ผู้ออกแบบจะสร้าง

CanvasWidth และ CanvasHeight เป็น wrapper CLR ของคุณสมบัติการพึ่งพา ค่าเหล่านี้ถูกกำหนดไว้ใน OnApplyTemplate() โดยการคูณขนาดของ GridUnitViewbox ด้วยจำนวนไทล์กริดที่ต้องอยู่ในการซ้อนทับของกริด กล่าวคือ ในกรณีส่วนใหญ่จะเป็นตารางขนาด 78x63

ชื่อ CanvasWidth และ CanvasHeight ฉันคิดว่าอาจทำให้เข้าใจผิดเล็กน้อยเนื่องจากไม่ได้อ้างถึงตัวควบคุม Canvas แต่หมายถึง Grid ที่เป็นที่เก็บ Canvas (อาจจำเป็นต้องเปลี่ยนรูปแบบการตั้งชื่อ) ที่กล่าวว่า CanvasHeight, CanvasWidth และ GridUnitViewbox ไม่ได้ขึ้นอยู่กับคุณสมบัติของตัวควบคุมใดๆ แต่เป็นการคำนวณที่ทำใน 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;
        }
    }

ตัวควบคุม Grid กำลังทำสิ่งที่ฉันต้องการจริงๆ VisualBrush และ Rectangle ภายในนั้นไม่ได้เชื่อมโยงอย่างถูกต้องหรือไม่ได้รับการอัปเดตอย่างถูกต้อง ความคิดเห็นด้านล่าง <Grid.Background> คือค่าทดสอบแบบฮาร์ดโค้ดที่ฉันใช้สำหรับ VisualBrush's Viewbox และ Viewport รวมถึงขนาดของ Rectangle ก่อนที่ฉันจะรวมค่าต่างๆ เข้าด้วยกัน และมันสร้างสิ่งที่มองเห็นออกมาอย่างชัดเจนว่าฉันกำลังทำอะไรอยู่ ฉันยังยืนยันด้วยว่าอันที่จริง 6 และ 11.3266666666667 เป็นค่าสำหรับมิติข้อมูลของ GridUnitViewbox ระหว่างรันไทม์

ฉันรู้สึกว่าการเชื่อมโยงกำลังสร้าง '0,0,0,0' เนื่องจากการซ้อนทับของกริดเป็นเพียงการแรเงาสีเทาที่กำลังกินทรัพยากรจำนวนมหาศาล จริงๆ แล้วล็อคโปรแกรมถ้าคุณซูมเข้าไป อย่างที่คุณเห็นในโค้ดฉันพยายามเพิ่ม AffectsMeasure และ AffectsParentMeasure ลงในตัวเลือก Metadata ของคุณสมบัติการพึ่งพาโดยหวังว่าบางที UI อาจไม่ได้รับการอัปเดตอย่างถูกต้องหลังจากอัปเดตขนาดของ GridUnitViewbox แล้ว แต่ฉันคิดผิด ฉันไม่แน่ใจว่ามันจะเป็นอะไรอีก


person SirBeastalot    schedule 11.03.2011    source แหล่งที่มา
comment
คุณจะต้องเจาะจงมากขึ้นและแจกแจงปัญหาของคุณ ไม่ต้องสงสัยเลยว่าผู้คนจะใช้เวลาศึกษามาร์กอัป XAML ชิ้นใหญ่นั้น   -  person Stephen Chung    schedule 11.03.2011


คำตอบ (2)


เอาล่ะ ในกรณีที่ใครพบปัญหาที่คล้ายกัน ฉันพบวิธีแก้ปัญหาแล้ว เห็นได้ชัดว่า VisualBrush ค่อนข้างจู้จี้จุกจิกเล็กน้อยเกี่ยวกับ TemplateBindings ฉันปรับ XAML ดังนั้นและแก้ไขปัญหาได้:

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

นี่คือ บทความที่ฉันได้รับข้อมูลมา

person SirBeastalot    schedule 11.03.2011

CanvasWidth และ CanvasHeight คืออะไร พวกเขาถูกกำหนดไว้แล้วหรือยัง?

นอกจากนี้ฉันเชื่อว่าผืนผ้าใบไม่มีขนาดเว้นแต่จะระบุไว้อย่างชัดเจน เมื่อคุณผูกเข้ากับมัน ความกว้าง/ความสูงอาจเป็นศูนย์

ลองใช้ ActualWidth และ ActualHeight หรือ Canvas หลังจากการเรนเดอร์ผ่านเพื่อดูว่ามีค่าใด ๆ หรือไม่ แต่ afaik จะไม่มีค่าใด ๆ เว้นแต่คุณจะระบุไว้

person Stephen Chung    schedule 11.03.2011