TheFaithfulLearner
TheFaithfulLearner

Reputation: 693

Same XAML 'template', different bindings - how to do

I don't think I worded it very well in the title, so let me explain a little better. Firstly, it's a WPF project using MVVM and C# and the question relates to the XAML.

What I have isn't strictly a 'template', but the repetition means that surely there's a way it can be condensed.

Let me start with the XAML of interest and it's not as complex as it looks.

<Expander ExpandDirection="Down" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" Margin="2" Header="{Binding VerbFormsViewModel_PresentIndicative.Name}">
    <Border BorderBrush="Black" CornerRadius="5,5,5,5" Margin="2" BorderThickness="2">
        <StackPanel>
            <StackPanel Orientation="Horizontal">
                <StackPanel Margin="2">
                    <TextBlock Margin="3" Text="{Binding VerbFormsViewModel_PresentIndicative.PlainPositive_Name}" TextAlignment="Center" FontSize="12"
                                           MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"/>
                    <TextBlock Margin="2">English translation:</TextBlock>
                    <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                                         Text="{Binding VerbFormsViewModel_PresentIndicative.PlainPositive_TranslationEnglish, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                    <TextBlock Margin="2">Japanese kanji:</TextBlock>
                    <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                                         Text="{Binding VerbFormsViewModel_PresentIndicative.PlainPositive_TranslationJapaneseKanji, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                    <TextBlock Margin="2">Japanese hiragana:</TextBlock>
                    <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                                         Text="{Binding VerbFormsViewModel_PresentIndicative.PlainPositive_TranslationJapaneseHiragana, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                    <TextBlock Margin="2">Japanese romaji:</TextBlock>
                    <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                                         Text="{Binding VerbFormsViewModel_PresentIndicative.PlainPositive_TranslationJapaneseRomaji, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                </StackPanel>

                <StackPanel Margin="2">
                    <TextBlock Margin="3" Text="{Binding VerbFormsViewModel_PresentIndicative.PlainNegative_Name}" TextAlignment="Center" FontSize="12"
                                           MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"/>
                    <TextBlock Margin="2">English translation:</TextBlock>
                    <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                                         Text="{Binding VerbFormsViewModel_PresentIndicative.PlainNegative_TranslationEnglish, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                    <TextBlock Margin="2">Japanese kanji:</TextBlock>
                    <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                                         Text="{Binding VerbFormsViewModel_PresentIndicative.PlainNegative_TranslationJapaneseKanji, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                    <TextBlock Margin="2">Japanese hiragana:</TextBlock>
                    <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                                         Text="{Binding VerbFormsViewModel_PresentIndicative.PlainNegative_TranslationJapaneseHiragana, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                    <TextBlock Margin="2">Japanese romaji:</TextBlock>
                    <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                                         Text="{Binding VerbFormsViewModel_PresentIndicative.PlainNegative_TranslationJapaneseRomaji, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                </StackPanel>

            </StackPanel>
        </StackPanel>
    </Border>
</Expander>

Now, as you can see, the entirety of the above rests on a binding to some object called VerbFormsViewModel_PresentIndicative. What this represents is the form of a verb, and there are other such forms. For example, past indicative which is 'VerbFormsViewModel_PastIndicative' in my program.

So what I want is to have all of this, but for all the other verb forms. One way I can do that is to just copy and paste this code ten or twelve more times and just change the details in the binding.

But is there a better way? I'd prefer a XAML solution if possible. I mean there's just so much shared except for the part at the start of the binding statement. The bit that comes after the dot (e.g. 'PlainPositive_TranslationEnglish') will be the same.

(There is a reason I have more stack panels than I appear to need. What I posted here was two blocks of text boxes and their surrounding controls. Actually each verb form requires eight; two rows of four.)

Upvotes: 0

Views: 46

Answers (1)

Shawn Kendrot
Shawn Kendrot

Reputation: 12465

Pull the same code into a UserControl, remove the first part of the binding (the VerbFormsViewModel_PresentIndicative.) Then use the control and set the DataContext to your viewmodel

Control:

<UserControl x:Class="TranslationApp.MyUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel Orientation="Horizontal">
        <StackPanel Margin="2">
            <TextBlock Margin="3" Text="{Binding PlainPositive_Name}" TextAlignment="Center" FontSize="12"
                       MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"/>
            <TextBlock Margin="2">English translation:</TextBlock>
            <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                     Text="{Binding PlainPositive_TranslationEnglish, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            <TextBlock Margin="2">Japanese kanji:</TextBlock>
            <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                     Text="{Binding PlainPositive_TranslationJapaneseKanji, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            <TextBlock Margin="2">Japanese hiragana:</TextBlock>
            <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                     Text="{Binding PlainPositive_TranslationJapaneseHiragana, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            <TextBlock Margin="2">Japanese romaji:</TextBlock>
            <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                     Text="{Binding PlainPositive_TranslationJapaneseRomaji, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
        </StackPanel>

        <StackPanel Margin="2">
            <TextBlock Margin="3"  Text="{Binding PlainNegative_Name}" TextAlignment="Center" FontSize="12"
                       MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"/>
            <TextBlock Margin="2">English translation:</TextBlock>
            <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                     Text="{Binding PlainNegative_TranslationEnglish, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            <TextBlock Margin="2">Japanese kanji:</TextBlock>
            <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                     Text="{Binding PlainNegative_TranslationJapaneseKanji, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            <TextBlock Margin="2">Japanese hiragana:</TextBlock>
            <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                     Text="{Binding PlainNegative_TranslationJapaneseHiragana, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            <TextBlock Margin="2">Japanese romaji:</TextBlock>
            <TextBox Margin="2" MinWidth="{StaticResource StandardTBoxMinWidthWide}" MaxWidth="{StaticResource StandardTBoxMaxWidthWide}" TextWrapping="Wrap"
                     Text="{Binding PlainNegative_TranslationJapaneseRomaji, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
        </StackPanel>

    </StackPanel>
</UserControl>

Using the control

<Expander>
    <views:MyUserControl DataContext="{Binding VerbFormsViewModel_PresentIndicative}"
</Expander>

Upvotes: 1

Related Questions