wpf prism and custom control - wpf

i need help with creation custom control and prism library.
custom control must have two columns. And using prism library i want
insert in region some view
what i have:
public class MyContentControl : Control
{
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object),
typeof(MyContentControl), null);
[Bindable(true)]
public object Content
{
get { return GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
public static readonly DependencyProperty Content2Property = DependencyProperty.Register("Content2", typeof(object),
typeof(MyContentControl), null);
[Bindable(true)]
public object Content2
{
get { return GetValue(Content2Property); }
set { SetValue(Content2Property, value); }
}
}
and ResoureDictionary
<Style TargetType="{x:Type local:MyContentControl}">
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyContentControl}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinition>
<ContentControl Grid.Column="0" Content="{TemplateBinding Content}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="IndianRed"/>
<ContentControl Grid.Column=1 Content="{TemplateBinding Content2}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Aqua" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
what i want is use it like
<MyContentControl>
<MyContentControl.Content1>
<ContentControl prism:RegionManager.RegionName="{x:Static constants:RegionNames.Content1_Region}"/>
</MyContentControl.Content1>
<MyContentControl.Content2>
<ContentControl prism:RegionManager.RegionName="{x:Static constants:RegionNames.Content2_Region}"/>
</MyContentControl.Content2>
</MyContentControl >

Related

How to set a property of a custom control from the main window?

I have a custom control, this is the generic.axml code:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Calendario"
xmlns:MyNamespace="clr-namespace:Calendario;assembly=Calendario"
xmlns:Converters="clr-namespace:Calendario.Converters">
<Converters:DateConverter x:Key="DateConverter"></Converters:DateConverter>
<Converters:DayBorderColorConverter x:Key="DayBorderColorConverter"></Converters:DayBorderColorConverter>
<Style TargetType="{x:Type local:CalendarioPersonalizado}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CalendarioPersonalizado}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<DockPanel>
<TextBlock Text="{Binding Date}" />
<Grid Height="30" DockPanel.Dock="Top">
</Grid>
<ItemsControl ItemsSource="{Binding Days}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{Binding ColorRecuadroExterno, Mode=TwoWay}" BorderThickness="1" Padding="0">
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
And I have my Calendario.cs with the dpendency property:
public static readonly DependencyProperty ColorRecuadroExternoProperty = DependencyProperty.Register("ColorRecuadroExterno", typeof(Brush), typeof(CalendarioPersonalizado));
public Brush ColorRecuadroExterno
{
get { return (Brush)GetValue(ColorRecuadroExternoProperty); }
set { SetValue(ColorRecuadroExternoProperty, value); }
}
And later in my main windows I use the control:
<local:CalendarioPersonalizado x:Name="cCalendario" ColorRecuadroExterno="Green"/>
The problem is that the border of the day in the calendar is not set to green like I have tried to set in the main window.
Also in the code behid I have tried this:
cCalendario.ColorRecuadroExterno = System.Windows.Media.Brushes.Green;
But the the color is not set.
What I want to do is set the color of the border in my custom cotrol from my main application.
Thanks.
If you put a Callback method in your local:CalendarioPersonalizado class and set your backround in this callback method. I think it is going to work.
public static readonly DependencyProperty ColorRecuadroExternoProperty = DependencyProperty.Register("ColorRecuadroExterno", typeof(Brush), typeof(CalendarioPersonalizado),
new PropertyMetadata(Brushes.Brown, Callback));
private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CalendarioPersonalizado obj = d as CalendarioPersonalizado;
obj.ColorRecuadroExterno.Background = (Brush)e.NewValue;
}
Your DependencyProperty is of type Brush. You can't implicitly convert "Green" to a Brush.
You either need to use a converter to convert a string representation of a color to a brush, or make your property type Color, and bind it to an appropriate property.

UserControl multiple datatemplate + templateselector

I need to show data inside a usercontrol in different ways depending on a flag.
To achieve this i tried the following, but using this control in the main view shows nothing.
<UserControl DataContext="**self**">
<UserControl.Resources>
<DataTemplate x:Key="mouseInputTemplate">
<TextBlock HorizontalAlignment="Center"><Run Text="{Binding Text}" /></TextBlock>
</DataTemplate>
<DataTemplate x:Key="touchInputTemplate">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image Source="{Binding ImageUri}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Width="{Binding ImageWidth}" Height="{Binding ImageHeight}" />
<TextBlock HorizontalAlignment="Center"><Run Text="{Binding Text}" /></TextBlock>
</StackPanel>
</DataTemplate>
<local:InputModeDataTemplateSelector x:Key="inputModeTemplateSelector"
MouseInputModeTemplate="{StaticResource mouseInputTemplate}"
TouchInputModeTemplate="{StaticResource touchInputTemplate}" />
</UserControl.Resources>
<ContentControl HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch" ContentTemplateSelector="{StaticResource inputModeTemplateSelector}" />
</UserControl>
What am i doing wrong?
Is there a better way to achieve that?
Thank to EdPlunkett and more research i found out it is better to
use a ContentPresenter here and instead of binding on DataContext=this bind like this (as alsways suggested when writing a UserControl)
DataContext="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type yourType}}}"
Code:
<UserControl.Resources>
<DataTemplate x:Key="touchInputTemplate">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image Source="{Binding ImageUri}" Width="64" Height="64" />
<TextBlock HorizontalAlignment="Center" Text="{Binding Text}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="mouseInputTemplate">
<TextBlock HorizontalAlignment="Center" Text="{Binding Text}" />
</DataTemplate>
<local:InputModeDataTemplateSelector x:Key="inputModeTemplateSelector"
MouseInputModeTemplate="{StaticResource mouseInputTemplate}"
TouchInputModeTemplate="{StaticResource touchInputTemplate}" />
</UserControl.Resources>
<Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type yourType}}}">
<ContentPresenter Content="{Binding}" ContentTemplateSelector="{StaticResource inputModeTemplateSelector}">
</Grid>
Your ContentPresenter idea is the correct way to do it with a DataTemplateSelector, and I should have thought of it myself.
But here's yet another way to do it, which unlike my first answer, actually solves all the problems you're having:
XAML (in practice the Style would probably be defined in a separate ResourceDictionary):
<Window
x:Class="TestApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestApplication"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
Title="MainWindow" Height="350" Width="525"
>
<Window.Resources>
<Style TargetType="local:TestControl">
<Setter Property="Background" Value="Gainsboro" />
<Style.Triggers>
<!-- The 0 value for the InputMode enum is Mouse, so this will be the default. -->
<Trigger Property="InputMode" Value="Mouse">
<Setter Property="Background" Value="Wheat" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TestControl}">
<Grid Background="{TemplateBinding Background}">
<TextBlock HorizontalAlignment="Center"><Run Text="{TemplateBinding Text}" /></TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="InputMode" Value="Touch">
<Setter Property="Background" Value="LightSkyBlue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TestControl}">
<Grid Background="{TemplateBinding Background}">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image
Source="{TemplateBinding ImageUri}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Width="{TemplateBinding ImageWidth}"
Height="{TemplateBinding ImageHeight}"
/>
<TextBlock HorizontalAlignment="Center"><Run Text="{TemplateBinding Text}" /></TextBlock>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<local:TestControl
ImageHeight="100"
ImageWidth="100"
Text="This is the test control"
ImageUri="http://www.optimizeagency.com/wp-content/uploads/2015/09/GoogleLogo.jpg"
/>
</Grid>
</Window>
C#:
using System;
using System.Windows;
using System.Windows.Controls;
namespace TestApplication
{
class TestControl : Control
{
public TestControl()
{
// If input mode may change at runtime, you'll need an event that fires when that
// happens and updates this property.
// UIUtilities.GetInputMode() is just a stub in this example.
InputMode = UIUtilities.GetInputMode();
}
#region InputMode Property
public InputMode InputMode
{
get { return (InputMode)GetValue(InputModeProperty); }
set { SetValue(InputModeProperty, value); }
}
public static readonly DependencyProperty InputModeProperty =
DependencyProperty.Register("InputMode", typeof(InputMode), typeof(TestControl),
new PropertyMetadata(InputMode.Mouse));
#endregion InputMode Property
#region Text Property
public String Text
{
get { return (String)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(String), typeof(TestControl),
new PropertyMetadata(null));
#endregion Text Property
#region ImageUri Property
// The TemplateBinding in the template can't coerce a string to an
// ImageSource, so we have to make that happen elsewhere.
public ImageSource ImageUri
{
get { return (ImageSource)GetValue(ImageUriProperty); }
set { SetValue(ImageUriProperty, value); }
}
public static readonly DependencyProperty ImageUriProperty =
DependencyProperty.Register("ImageUri", typeof(ImageSource), typeof(TestControl),
new PropertyMetadata(null));
#endregion ImageUri Property
#region ImageHeight Property
public float ImageHeight
{
get { return (float)GetValue(ImageHeightProperty); }
set { SetValue(ImageHeightProperty, value); }
}
public static readonly DependencyProperty ImageHeightProperty =
DependencyProperty.Register("ImageHeight", typeof(float), typeof(TestControl),
new PropertyMetadata(float.NaN));
#endregion ImageHeight Property
#region ImageWidth Property
public float ImageWidth
{
get { return (float)GetValue(ImageWidthProperty); }
set { SetValue(ImageWidthProperty, value); }
}
public static readonly DependencyProperty ImageWidthProperty =
DependencyProperty.Register("ImageWidth", typeof(float), typeof(TestControl),
new PropertyMetadata(float.NaN));
#endregion ImageWidth Property
}
#region This stuff belongs in a different file
public static class UIUtilities
{
public static InputMode GetInputMode()
{
// Here you'd do whatever you're already doing to detect the input mode
return InputMode.Touch;
}
}
public enum InputMode
{
Mouse,
Touch
}
#endregion This stuff belongs in a different file
}

How to get image source in Control Template

I've added one button like this:
<Button x:Name="myButton"
Style="{StaticResource myButtonStyle}"
Height="36"
VerticalAlignment="Top"
Click="myButton_Click">
<Grid>
<Image Height="*" Width="31" Source="{Binding Path=Image}" />
<TextBlock Text="{Binding Path=DisplayName}" HorizontalAlignment="Center" />
</Grid>
</Button>
Where 'Image' is the source of the required image in string. And the style is as follows:
<Style x:Key="myButtonStyle"
TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="myButtonRootBorder">
<StackPanel Orientation="Horizontal">
<Image Source="{??}" Width="{??}" Height="{??}" />
<!--ContentPresenter-->
<ContentPresenter Grid.Column="1"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}" />
</StackPanel
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now how to set the height, width and source of the image in the control template.
Please help. Thanks in advance.
For width and height you can use {TemplateBinding Width} and {TemplateBinding Height}. If you want the image to be customizable you should inherit the button class and add an imagesource property:
public class ImageButton : Button {
public ImageSource ImageSource
{
get { return (ImageSource)GetValue(ImageSourceProperty); }
set { SetValue(ImageSourceProperty, value); }
}
// Using a DependencyProperty as the backing store for ImageSource. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ImageSourceProperty =
DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(ImageButton), new UIPropertyMetadata(null));
}
Then you can use {TemplateBinding ImageSource} for the image.

How do I get WPF searchbox styling like GoogleChrome browser search?

I am planning to have search functionality in WPF like it happens in Google Chrome browser. The sample is shown below
I have the backend code ready, but I want to have a TextBox like the one shown below - in which I can display the results also(like 0 of 0).
Also I would like to have the arrow marks for next and prev.
How do I design such a TextBox in WPF in XAML? Please guide me regarding the same.
A custom control can be created using following code:
public class SearchTextBox : Control
{
public String Text
{
get { return (String)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
// Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(String), typeof(SearchTextBox), new UIPropertyMetadata(null));
public String SearchStatusText
{
get { return (String)GetValue(SearchStatusTextProperty); }
set { SetValue(SearchStatusTextProperty, value); }
}
// Using a DependencyProperty as the backing store for SearchStatusText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SearchStatusTextProperty =
DependencyProperty.Register("SearchStatusText", typeof(String), typeof(SearchTextBox), new UIPropertyMetadata(null));
static SearchTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SearchTextBox), new FrameworkPropertyMetadata(typeof(SearchTextBox)));
}
}
Style in Generic.xaml
<Style TargetType="{x:Type local:SearchTextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:SearchTextBox}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0"
Text="{TemplateBinding Text}" />
<TextBlock Grid.Column="1"
Text="{TemplateBinding SearchStatusText}"></TextBlock>
<Button Grid.Column="2">
<Polyline Points="0,10 5,0 10,10"
Stroke="Black"
StrokeThickness="2" />
</Button>
<Button Grid.Column="3">
<Polyline Points="0,0 5,10 10,0"
Stroke="Black"
StrokeThickness="2" />
</Button>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You will need to change it according to your needs. But this should be a good starting point.
There is no Ready made solution for your requirement.You have to fiddle quite a few with the controltemplates of existing controls or you can build a custom control from scratch.
http://msdn.microsoft.com/en-us/library/aa970773%28VS.85%29.aspx

Issue binding Image Source dependency property

I have created a custom control for ImageButton as
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Local:ImageButton}">
<StackPanel Height="Auto" Orientation="Horizontal">
<Image Margin="0,0,3,0" Source="{Binding ImageSource}" />
<TextBlock Text="{TemplateBinding Content}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
ImageButton class looks like
public class ImageButton : Button
{
public ImageButton() : base() { }
public ImageSource ImageSource
{
get { return base.GetValue(ImageSourceProperty) as ImageSource; }
set { base.SetValue(ImageSourceProperty, value); }
}
public static readonly DependencyProperty ImageSourceProperty =
DependencyProperty.Register("Source", typeof(ImageSource), typeof(ImageButton));
}
However I'm not able to bind the ImageSource to the image as:
(This code is in UI Folder and image is in Resource folder)
<Local:ImageButton x:Name="buttonBrowse1" Width="100" Margin="10,0,10,0"
Content="Browse ..." ImageSource="../Resources/BrowseFolder.bmp"/>
But if i take a simple image it gets displayed if same source is specified.
Can anyone tell me what shall be done?
You need to replace the Binding in your ControlTemplate by a TemplateBinding, just as you did for the Content property:
<Image Margin="0,0,3,0" Source="{TemplateBinding ImageSource}" />
Furthermore, the definition of your DependencyProperty is not correct. The string should read ImageSource instead of just Source:
DependencyProperty.Register("ImageSource", typeof(ImageSource), ...
I do not know whether/where this name conflict causes any problems, but at least it is highly recommended to use the exact name of the actual CLR property.
EDIT: You will also have to change the TargetType of your Style to your ImageButton:
<Style TargetType="{x:Type Local:ImageButton}">

Resources