Click here to Skip to main content
15,511,378 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a modal use control. It will be used in many places. The different part is the message part.

I am not sure how to make it re-useful.
<Grid Margin="10">
                <Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
                        <StackPanel Margin="10">
                                <TextBlock Text="{Binding Message}" />
                        </StackPanel>
                </Border>
</Grid>

Need code rather than concept statements.

What I have tried:

Tried to use content template or datatemplate. Just don't know how to apply it.
Posted
Updated 29-Nov-17 23:07pm
Comments
Graeme_Grant 16-Nov-17 0:05am    
"Tried to use content template or datatemplate. Just don't know how to apply it." -
This link may help: Creating and Consuming Resource Dictionaries in WPF and Silverlight – WPF & Silverlight Designer[^]

Here are the steps to do what you ask:

1. In the Solution Explorer, right-click on your solution > Add > New Project & select "WPF UserControl Library (.Net Framework), give it a name and click on the OK button.

2. Now Add a UserControl with a given name. Pretty it up with Xaml and add functionality with code then compile.

3. Add a reference in the project that wants to use it.

4. Then in your Xaml, add a Namespace reference to the UserControl in your new external UserControl library

5. Add the UserControl to your Xaml.

If you want to see how it is done with code, then have a look at this article: Flexible WPF ToggleSwitch Lookless Control in C# & VB[^] - not a UserControl but same principle (as described above) applies.

UPDATE Threw this together whilst having lunch:

1. UserControlLib to hold our shared UserControls. Here is your UserControl called MySharedUserControl:
XML
<UserControl
    x:Class="UserControlLib.MySharedUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Grid Margin="10">
        <Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
            <StackPanel Margin="10">
                <TextBlock Text="{Binding Message}" />
            </StackPanel>
        </Border>
    </Grid>

</UserControl>


2. Our test App WpfApp1 with a reference added to our UserControlLib UserControl lib:

Code-Behind for the MainWindow:
C#
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;

namespace WpfApp1
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        private string message;
        public string Message
        {
            get { return message; }
            set
            {
                message = value;
                RaisePropertyChanged();
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Message = "Test Message";
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

And the Xaml:
XML
<Window
    x:Class="WpfApp1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:MyLib="clr-namespace:UserControlLib;assembly=UserControlLib"
    Title="MainWindow" Height="350" Width="525">

    <Grid>
        <Button Content="Show Message" Click="Button_Click"
                VerticalAlignment="Top" HorizontalAlignment="Center"
                Margin="20" Padding="10 5"/>

        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <TextBlock Text="MESSAGE:" Margin="0 0 10 0" VerticalAlignment="Center"/>
            <MyLib:MySharedUserControl Width="200" Grid.Column="1"/>
        </Grid>
    </Grid>

</Window>

Our UserControl Lib and the control NameSpace is added to the header: xmlns:MyLib="clr-namespace:UserControlLib;assembly=UserControlLib" and the control is used with our NameSpace: <MyLib:MySharedUserControl Width="200" Grid.Column="1"/>
 
Share this answer
 
v2
I wouldn't use a template here. Templates are meant to override or provide the UI elements, but if all that's changing is the message content you simply need an exposed binding.

In your code behind do this:
public partial class MyReusedView : UserControl
{
    public static DependencyProperty MessageProperty = DependencyProperty.Register("Message", typeof(string), typeof(MyReusedView));

    public string Message
    {
        get { return (string)GetValue(MessageProperty); }

        set { SetValue(MessageProperty, value); }
    }

    public MyReusedView()
    {
        InitializeComponent();

        DataContext = this;
    }
}

Then all you need in XAML is:
<common:MyReusedView Message={Binding MyMessageSource.Message}/>

As kind of implied by the namespace, just make sure to put the class at a high enough level so you can reference it appropriately in other assemblies.

If your modal control has a view model as the DataContext already, then you can use this in the constructor:
public MyReusedView()
{
    InitializeComponent();

    DataContext = new MyReusedViewModel();

    Binding messageBinding = new Binding("Message");
    messageBinding.Source = DataContext;
    messageBinding.Mode = BindingMode.OneWayToSource;
    SetBinding(MyReusedView.MessageProperty, messageBinding);
}

Such that you can keep any other logic in the view model and just expose the property through the view so it can be accessed via XAML.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900