เชื่อมต่อสตริงแทนการใช้ TextBlocks ซ้อนกัน


91

ฉันต้องการแสดงรายการอ็อบเจ็กต์ของลูกค้าใน WPF ItemsControl ฉันได้สร้าง DataTemplate สำหรับสิ่งนี้:

    <DataTemplate DataType="{x:Type myNameSpace:Customer}">
        <StackPanel Orientation="Horizontal" Margin="10">
            <CheckBox"></CheckBox>
            <TextBlock Text="{Binding Path=Number}"></TextBlock>
            <TextBlock Text=" - "></TextBlock>
            <TextBlock Text="{Binding Path=Name}"></TextBlock>
        </StackPanel>
    </DataTemplate>

ดังนั้นสิ่งที่ฉันต้องการโดยทั่วไปคือรายการง่ายๆ (พร้อมช่องทำเครื่องหมาย) ที่มี NUMBER - NAME ไม่มีวิธีใดที่ฉันสามารถต่อหมายเลขและชื่อในส่วนการผูกได้โดยตรง?

คำตอบ:


175

มีคุณสมบัติ StringFormat (ใน. NET 3.5 SP1) ซึ่งคุณอาจใช้ได้ และมีประโยชน์ WPF ผูกพันโกง sheat สามารถพบได้ที่นี่ หากไม่ได้ผลคุณสามารถเขียน ValueConverter หรือคุณสมบัติที่กำหนดเองสำหรับวัตถุของคุณได้ตลอดเวลา

เพิ่งตรวจสอบคุณสามารถใช้ StringFormat กับ multibinding ในรหัสกรณีของคุณจะเป็นดังนี้:

<TextBlock>
  <TextBlock.Text>
    <MultiBinding StringFormat=" {0} - {1}">
        <Binding Path="Number"/>
        <Binding Path="Name"/>
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>

ฉันต้องเริ่มจัดรูปแบบสตริงด้วยช่องว่างมิฉะนั้น Visual Studio จะไม่สร้าง แต่ฉันคิดว่าคุณจะหาทางหลีกเลี่ยงได้ :)

แก้ไข
ช่องว่างจำเป็นใน StringFormat เพื่อป้องกันไม่ให้ parser ถือว่า{0}เป็นการรวมข้อมูล ทางเลือกอื่น ๆ :

<!-- use a space before the first format -->
<MultiBinding StringFormat=" {0} - {1}">

<!-- escape the formats -->
<MultiBinding StringFormat="\{0\} - \{1\}">

<!-- use {} before the first format -->
<MultiBinding StringFormat="{}{0} - {1}">

29
แทนที่จะเป็นช่องว่างที่คุณสามารถใช้ {} เช่น StringFormat = "{} {0} - {1}"
Bryan Anderson

6
คุณยังสามารถหลีกเลี่ยงเครื่องหมายวงเล็บด้วยแบ็กสแลช: <MultiBinding StringFormat = "\ {0 \} - \ {1 \}">
hughdbrown

นอกจากนี้ TextBlock ปิดก็หายไปดังนั้นเพื่อสรุปความคิดเห็น: <TextBlock> <TextBlock.Text> <MultiBinding StringFormat = "{} {0} - {1}"> <Binding Path = "Number" /> <Binding Path = "Name" /> </MultiBinding> </TextBlock.Text> </TextBlock>
TJKjaer

@PiRX หากฉันต้องการแสดง 'หมายเลข' แม้ว่า 'ชื่อ' จะว่างเปล่า - ฉันจะทำอย่างไร
DasDas

@DasDas น่าเสียดายที่ฉันไม่สามารถช่วยตอบคำถามของคุณได้เนื่องจากฉันไม่ได้ทำงานกับ WPF มาหลายปีแล้ว เป็นเรื่องตลกที่คุณลืมสิ่งที่คุณไม่ได้ใช้งานไปแล้วเร็วแค่ไหน
PiRX

66

ในกรณีที่คุณต้องการต่อค่าไดนามิกกับข้อความคงที่ให้ลองทำดังนี้:

<TextBlock Text="{Binding IndividualSSN, StringFormat= '\{0\} (SSN)'}"/>

แสดง : 234-334-5566 (SSN)


1
เนื้อหาของ TextBlockLeftStyle คืออะไร?
itsho

มันเป็นสไตล์ที่กำหนดเองฉันต้องจัดแนวบล็อกข้อความไปทางซ้าย มันไม่มีความสำคัญที่นี่
redskull

1
นี่เป็นทางออกที่ดีที่สุดในการเชื่อมการโยงเข้ากับสตริง
Devid

9

ดูตัวอย่างต่อไปนี้ที่ฉันใช้ในโค้ดของฉันโดยใช้คลาส Run:

        <TextBlock x:Name="..." Width="..." Height="..."
            <Run Text="Area="/>
            <Run Text="{Binding ...}"/>
            <Run Text="sq.mm"/>
            <LineBreak/>
            <Run Text="Min Diameter="/>
            <Run Text="{Binding...}"/>
            <LineBreak/>
            <Run Text="Max Diameter="/>
            <Run Text="{Binding...}"/>
        </TextBlock >

3

คุณยังสามารถใช้การรันแบบผูกได้ สิ่งที่มีประโยชน์โดยเฉพาะอย่างยิ่งหากต้องการเพิ่มการจัดรูปแบบข้อความ (สีแบบอักษร ฯลฯ )

<TextBlock>
   <something:BindableRun BoundText="{Binding Number}"/>
   <Run Text=" - "/>
   <something:BindableRun BoundText="{Binding Name}"/>
</TextBlock>

นี่คือคลาสดั้งเดิม:
นี่คือการปรับปรุงเพิ่มเติมบางส่วน
และนั่นคือทั้งหมดในโค้ดชิ้นเดียว:

public class BindableRun : Run
    {
        public static readonly DependencyProperty BoundTextProperty = DependencyProperty.Register("BoundText", typeof(string), typeof(BindableRun), new PropertyMetadata(new PropertyChangedCallback(BindableRun.onBoundTextChanged)));

        private static void onBoundTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((Run)d).Text = (string)e.NewValue;
        }

        public String BoundText
        {
            get { return (string)GetValue(BoundTextProperty); }
            set { SetValue(BoundTextProperty, value); }
        }

        public BindableRun()
            : base()
        {
            Binding b = new Binding("DataContext");
            b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(FrameworkElement), 1);
            this.SetBinding(DataContextProperty, b);
        }
    }

1
<เรียกใช้ Text = "{Binding ... }" />? อธิบายข้อดีได้ไหม
Felix Keil

1
ไม่แตกต่าง; Run ไม่รองรับการผูกในคุณสมบัติ Text เมื่อ 10 ปีก่อนเมื่อคำตอบนี้ถูกเขียน!
josh2112
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.