2009-09-15 12 views
7

Mam następujący kod wyświetlający wiek klientów.Tekst mieszania WPF i tekstu stałego w TextBox

<TextBox x:Name="txtClientAge" Text="{Binding Path=ClientAge}" /> 

Jednak zamiast po prostu wyświetlanie tylko liczby, chcę prefiks z tekstem „wiek” i sufiks go z tekstem „yrs”, więc jest skutecznie staje „Wiek 36 yrs”

Mogę to osiągnąć za pomocą poziomego StackPanel i 3 pól tekstowych, ale czy istnieje o wiele prostsza metoda, której mi brakuje?

+0

Czy chcesz, aby części "wiek" i "lata" były edytowalne? To znaczy. czy użytkownik powinien móc wpisać "wiek 40 lat" (lub może po prostu "40") w polu tekstowym w całości i czy jest poprawnie przetwarzany? –

+0

W każdym przypadku, jeśli w aplikacji jest tylko jeden taki tekst (tzn. Nie trzeba go ponownie używać), rozwiązanie StackPanel + 2 TextBlocks + TextBox będzie najprostsze. –

+0

Ma być używany tylko do odczytu, nie wymaga aktualizacji. – Mitch

Odpowiedz

8

Zakładając, że nie potrzebujesz wartości wieku do edycji, w WPF 4.0 właściwość Text Run będzie wiążąca, to prawdopodobnie nie pomoże Ci teraz, chyba że korzystasz z przedpremierowego wydania, ale będziesz w stanie zrobić coś jak następuje:

<TextBlock x:Name="txtClientAge" > 
    <Run Text="Age "/><Run Text="{Binding Path=ClientAge}"/><Run Text=" Yrs"/> 
</TextBlock> 

UPDATE Herezje kolejna alternatywa dla rozwiązania ciąg formatu, który będzie działał, ale nie jest szczególnie ładna (w rzeczywistości jego dość hacky). Użyj następującego konwertera na wiązanie (zakładając własności klientelizmu jest typu int):

public class AgeConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, 
          System.Globalization.CultureInfo culture) 
    { 
     string age = value.ToString(); 
     return "Age " + age + " years"; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, 
           System.Globalization.CultureInfo culture) 
    { 
     string age = value as string; 
     return Int32.Parse(age.Replace("Age ", " ").Replace(" years", "")); 
    } 
} 
+0

Dzięki Simon, tego właśnie szukałem, ale jak już mówisz, nie jest to jeszcze z nami! Być może będę musiał przyjąć podejście z długą kuracją do czasu, aż WPF 4.0 będzie z nami. – Mitch

+0

Miły kawałek kolega myślenia lateralnego. Obecnie cieszę się z używania Konwerterów do różnych rzeczy, więc Twoje podejście naprawdę się podoba. Dziękuję za to! – Mitch

+0

Tak, ConvertBack to część, której nie lubię, ale ponieważ jest to sytuacja tylko do odczytu, która nie będzie stanowić problemu. –

5

Można utworzyć własność w klasie, która również jest oprawa, która tworzy ciąg tekstowy, który chcesz wyświetlić.

Jest też droga StringFormat:

<textblock text="{Binding Path=mydate, StringFormat=d}"/> 

można siekać stałe do łańcucha formatowania.

Preferuję metodę właściwości.

+3

To zasadniczo modyfikuje twój model, aby był świadomy widoku - bardzo zły pomysł z punktu widzenia projektu. –

+1

+1 dla StringFormat. Zgadzam się z @Pavel - nie twórz właściwości z tym tekstem. – Andy

+2

Jeśli naprawdę chcesz to zrobić w prawidłowy sposób, tekst również nie należy do widoku. Musi znajdować się w obszarze zasobów wybranym przez warstwę prezentacji na podstawie bieżącego ustawienia kultury. Dlatego wszystkie moje rzeczy pochodzą z właściwości prezenterów. – Jay

5

Jest to dość stare pytanie, ale myślę, że to jest obecny najlepszym rozwiązaniem (jeśli chcesz do edycji tekstu).

Można to zrobić za pomocą InlineUIContainer w TextBlock z zagnieżdżonym Textbox.

Uwaga: użyłem BaselineAlignment="Center" do wyrównania komponentów. W razie potrzeby można również dodać marginesy dodatnie lub ujemne do TextBox. Również ustawiam granicę TextBox jako przezroczystą, aby wyglądała jak część TextBlock, mimo że jest edytowalna i możliwa do wybrania.

<TextBlock Foreground="SteelBlue"> 
    <Run Text="Package Barcode:" FontWeight="Bold" BaselineAlignment="Center"/> 
    <InlineUIContainer BaselineAlignment="Center"> 
     <TextBox Margin="2,0,0,0" Foreground="Gray" Text="{Binding BarcodeNumber}" BorderThickness="0" Padding="0"/> 
    </InlineUIContainer> 
</TextBlock> 
+1

tak, zdaję sobie sprawę, że pierwotny pytający ostatecznie chciał, aby "wiek" był tylko do odczytu - ale jest to odpowiedź na postawione pytanie :-) –

1

To jest jak poprzedniej odpowiedzi - (ale wszystkie są z Texblocks ... więc tutaj wersja tekstowe), ja też chciałem pokazać podejście MultiBinding. Aby uzyskać Texbox do robienia tego, co chcesz, można użyć następującego kodu:

<TextBox> 
<TextBox.Text> 
    <MultiBinding StringFormat="Age {0} yrs and {1} months"> 
    <Binding Path="Years" /> 
    <Binding Path="Months" /> 
    </MultiBinding> 
</TextBox.Text> 
</TextBox> 

Może to być przydatne, jeśli chcesz, aby Twój tekst do wyboru, więc użytkownik może skopiować kod.