2

I'm looking for a best practise in the following scenario. This scenario has been made up just to illustrate the problem in a simplified manner.

Assuming we have the following Layout, to store an address. Layout in WPF

Though some customers might think, the e-mail is more important than the name, and hence would like to display it before the name. Some customers might need more space for the name. Some customers cry because they don't need any phone numbers at all.

My goal: The user should be able to decide, how his form looks like.

I would like to set up a default template which should work for most customers.

I prefer not to reinvent the wheel, so is there any library which provides such functionality?

Such functionality could be (at runtime):

  • Reorder Controls (e.g. with drag and drop)
  • Store and Load UI Layout Templates
  • Set Controls Visible / Invisible
  • Resize Controls

If not, what would be the "best practise" to solve this?


If I had to reinvent the wheel, the most probable solution would be to create my own XML, which I would load at runtime and then set the rows and columns. But since I'm quite new to WPF, I don't know if this was a proper solution.


At last, below is the XAML of the above example:

<Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
                <RowDefinition Height="28" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Label Grid.Row="0" Grid.Column="0" Content="Name:"/>
            <Label Grid.Row="1" Grid.Column="0" Content="E-Mail:"/>
            <Label Grid.Row="2" Grid.Column="0" Content="Phone:"/>
            <Label Grid.Row="3" Grid.Column="0" Content="Address:"/>
            <TextBox Grid.Column="1" Grid.Row="0" Margin="3" />
            <TextBox Grid.Column="1" Grid.Row="1" Margin="3" />
            <TextBox Grid.Column="1" Grid.Row="2" Margin="3" />
            <TextBox Grid.Column="1" Grid.Row="3" Margin="3" />
            <Button Grid.Column="1" Grid.Row="4" HorizontalAlignment="Right" MinWidth="80" Margin="3" Content="OK" Click="Button_Click"  />
</Grid>
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Fabian Bigler
  • 10,403
  • 6
  • 47
  • 70

2 Answers2

1

Firstly, it is good that you ask this question before creating the application. Secondly, I think to this task dynamically creating View perfect come up DataTemplate. You should begin right away to develop your application in MVVM style, it would be more appropriate for dynamic View.

In the DataTemplate, the key role played DataTrigger. They allow depending on the value set property for an element that is in View. For example, the show / hide button, set the Height / Width, etc.

Example of DataTemplate:

<DataTemplate x:Key="MainView" DataType="{x:Type ViewModels:MainViewModel}">
    <Grid>
        <Button Name="UserButton"
                Content="Are you user?"
                Width="100"
                Height="30"
                HorizontalAlignment="Left"
                VerticalAlignment="Top"
                Command="{Binding UserButtonCommand}" />

        <Button Name="AdminButton"
                Content="Are you admin?"
                Width="100"
                Height="30"
                HorizontalAlignment="Right"
                VerticalAlignment="Top"
                Command="{Binding AdminButtonCommand}" />

        <StackPanel Name="MainViewPanel"
                    Tag="{Binding Path=MainModel.ContentType,
                                  Mode=TwoWay, 
                                  UpdateSourceTrigger=PropertyChanged}">

            <TextBlock Name="TitleTextBlock"
                       Text="{Binding Path=MainModel.TitleText,
                                      Mode=TwoWay, 
                                      UpdateSourceTrigger=PropertyChanged}"
                       FontSize="20"
                       HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Visibility="Collapsed" />

            <TextBox Name="BannedTextBlock"
                     Text="{Binding Path=MainModel.BannedName,
                                    Mode=TwoWay, 
                                    UpdateSourceTrigger=PropertyChanged}"
                     Visibility="Collapsed" />

            <Button Name="YesButton" 
                    Content="{Binding Path=MainModel.ContentYesButton,
                                      Mode=TwoWay, 
                                      UpdateSourceTrigger=PropertyChanged}" 
                    Visibility="Collapsed" />

            <Button Name="NoButton" 
                    Content="{Binding Path=MainModel.ContentNoButton,
                                      Mode=TwoWay, 
                                      UpdateSourceTrigger=PropertyChanged}" 
                    Visibility="Collapsed" />
        </StackPanel>
    </Grid>

    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding ElementName=MainViewPanel, Path=Tag}" Value="User">
            <Setter TargetName="TitleTextBlock" Property="Visibility" Value="Visible" />
            <Setter TargetName="YesButton" Property="Visibility" Value="Visible" />
        </DataTrigger>

        <DataTrigger Binding="{Binding ElementName=MainViewPanel, Path=Tag}" Value="Admin">
            <Setter TargetName="TitleTextBlock" Property="Visibility" Value="Visible" />
            <Setter TargetName="BannedTextBlock" Property="Visibility" Value="Visible" />
            <Setter TargetName="YesButton" Property="Visibility" Value="Visible" />
            <Setter TargetName="NoButton" Property="Visibility" Value="Visible" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

Given two buttons, one for the user and one for the administrator. If you choose the User, the content is displayed to the user, if the Admin, then for administrator. Content type specified in the Tag of StackPanel. Pay attention to the section <DataTemplate.Triggers>.

Complete example and description of an example is here (he still quite large):

Make (create) reusable dynamic Views

Community
  • 1
  • 1
Anatoliy Nikolaev
  • 22,370
  • 15
  • 69
  • 68
0

For the reordering part, you can combine Anatoliy Nikolaev's answer with a listbox and Gong Drag and Drop reorder => https://github.com/punker76/gong-wpf-dragdrop

The default layout of the listbox can easily be changed so that you don't have the selected items highlighting and so on.

You might also consider to provide two dynamic views, one for the actual form and one to edit the said form. Also at some point you will have to save the configuration for each user.

woutervs
  • 1,500
  • 12
  • 28