.NET Core WPF User Control set design-time background - wpf

I tried the two methods explained in this existing answer, but neither of them is working. How can I set the background colour?
Method 1
<UserControl x:Class="deletewpf.UserControl1"
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"
xmlns:local="clr-namespace:deletewpf"
mc:Ignorable="d"
d:DesignStyle="{StaticResource MyDesignStyle}"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Style TargetType="{x:Type Control}" x:Key="MyDesignStyle">
<Setter Property="Background" Value="White"/>
</Style>
</UserControl.Resources>
<Grid>
</Grid>
</UserControl>
Method 2
<UserControl x:Class="deletewpf.UserControl2"
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"
xmlns:local="clr-namespace:deletewpf"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<d:DesignerProperties.DesignStyle>
<Style TargetType="UserControl">
<Setter Property="Background" Value="White"/>
</Style>
</d:DesignerProperties.DesignStyle>
<Grid>
</Grid>
</UserControl>
I had pressed Run to build it before getting those errors.

This is an issue with the .NET Core designer. In .NET Framework both methods work, but for the first method, you would have to use a DynamicResource, because the style is declared after it is used.
d:DesignStyle="{DynamicResource MyDesignStyle}"
There is a workaround for .NET Core, that is also included in one of the answers. You have to declare a type that defines attached dependency properties that check if you are running design mode and sets the corresponding properties. This is an example for the Background property only, but it can be extend for using a Style, too.
public class DesignModeProperties : DependencyObject
{
public static readonly DependencyProperty BackgroundProperty = DependencyProperty.RegisterAttached(
"BackgroundProperty", typeof(Brush), typeof(DesignModeProperties),
new FrameworkPropertyMetadata(Brushes.Transparent, OnBackgroundChanged));
public static void OnBackgroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (DesignerProperties.GetIsInDesignMode(d) && d is Control control && e.NewValue is Brush brush)
control.Background = brush;
}
public static Brush GetBackground(DependencyObject dependencyObject)
{
return (Brush)dependencyObject.GetValue(BackgroundProperty);
}
public static void SetBackground(DependencyObject dependencyObject, Brush value)
{
dependencyObject.SetValue(BackgroundProperty, value);
}
}
Add the following line to your UserControl markup to enbale the design-mode background.
local:DesignModeProperties.Background="White"

Related

XAML: Bind to a property of a custom control from a Template

in my WPF app I have a custom control with a dependency object
public static readonly DependencyProperty SomeFieldProperty =
DependencyProperty.Register("SomeField", typeof(double), typeof(MyControl), new PropertyMetadata((double)0, OnPropChanged));
public double SomeField
{
get { return (double)GetValue(SomeFieldProperty ); }
set { SetValue(SomeFieldProperty , value); }
}
And from my XAML I'm trying to bind to SomeField like below but it doesn't work:
UPDATED:
<UserControl.Template>
<ControlTemplate TargetType="ContentControl">
<WrapPannel >
<abc:MyControl SomeField="{Binding SomeValue, Mode=TwoWay}" />
</WrapPannel>
</ControlTemplate>
</UserControl.Template>
Tried different solutions suggested in this like questions in the StackOverflow but none of them worked. Maybe my case is a specific one as I am trying to bind from within a template?
Looks like it is not a binding problem. Actually the Template property of a UserControl is overrideb by InitializeComponent().
Something like this will work:
<UserControl x:Class="WPF.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"
xmlns:local="clr-namespace:WPF"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<WrapPannel>
<abc:MyControl SomeField="{Binding SomeValue, Mode=TwoWay}" />
</WrapPannel>
</UserControl>
Actually UserControls are to be used when Templates are not needed. Otherwise use Controls, ContentControls or ItemsControls.

Setting ImageSource From Style Resource on UserControl

I have created a User Control that has an image component inside bound to a DependencyProperty. Everything works great at runtime, but I can not see the image in Design Time.
ButtonBase.xaml:
<UserControl x:Class="VirtualEnvelopes.ButtonBase"
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"
xmlns:local="clr-namespace:VirtualEnvelopes"
x:Name="ButtonRoot">
<UserControl.Resources>
<BitmapImage x:Key="DefaultImage" UriSource="/assets/common/nullButton.png" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Grid>
<Image x:Name="MainImageBitmap" Source="{Binding Path=MainImage, ElementName=ButtonRoot, TargetNullValue={StaticResource DefaultImage}}" Tag="{Binding Path=Tag, ElementName=ButtonRoot}" />
</Grid>
</Grid>
</UserControl>
ButtonBase.xaml.cs
public partial class ButtonBase : UserControl
{
public static readonly DependencyProperty MainImageProperty =
DependencyProperty.Register("MainImage", typeof(Uri), typeof(ButtonBase), new UIPropertyMetadata(null));
public Uri MainImage
{
get { return (Uri)GetValue(MainImageProperty); }
set { SetValue(MainImageProperty, value); }
}
public ButtonBase()
{
InitializeComponent();
}
}
Usage:
<Window x:Class="VirtualEnvelopes.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:base="clr-namespace:VirtualEnvelopes">
<Window.Resources>
<Style x:Key="Button1Style" TargetType="{x:Type base:ButtonBase}">
<Setter Property="MainImage" Value="pack://application:,,,/pathToImage.png" />
</Style>
</Window.Resources>
<Canvas Width="1000" Height="1000">
<base:ButtonBase Style="{StaticResource Button1Style}" Tag="1" />
<base:ButtonBase MainImage="pack://application:,,,/pathToImage.png" Tag="2" />
</Canvas>
</Window>
Both buttons show at runtime, but only button #2 can be seen in the design space. The value line in the setter for Button1Style is underlined and says "specified method is not supported".
I've tried image asset as Content and Resource and it doesn't seem to make any difference. How can I get this image to show in design time and run time? There will eventually be many of these buttons and I need to lay them out specifically on the canvas at design time.
Any help would be appreciated.

Is there a way to respond to double-clicking on a ListBoxItem in WPF?

I have a simple WPF application with a ListBox of items. For the simplicity of this example, I made it a list of strings, but in reality, it will be a list of some complex type. When an item itself in the listbox is double clicked, I want to respond to it. Apparently, there is no direct double click event on the ListBox for the item itself. Is there a simple way of responding to an item in the ListBox being double-clicked (not the listbox itself)?
Here is my xaml:
<Window x:Class="WpfApplication12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox>
<ListBox.Items>
<sys:String>Item1</sys:String>
<sys:String>Item2</sys:String>
<sys:String>Item3</sys:String>
<sys:String>Item4</sys:String>
<sys:String>Item5</sys:String>
</ListBox.Items>
</ListBox>
</Grid>
</Window>
This can be easily achieved by creating an ItemContainerStyle and adding an EventSetter.
Modify your XAML like so:
<Window x:Class="WpfApplication12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<EventSetter Event="MouseDoubleClick" Handler="ListBoxItem_DoubleClick" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Items>
<sys:String>Item1</sys:String>
<sys:String>Item2</sys:String>
<sys:String>Item3</sys:String>
<sys:String>Item4</sys:String>
<sys:String>Item5</sys:String>
</ListBox.Items>
</ListBox>
</Grid>
</Window>
The code-behind:
namespace WpfApplication12
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ListBoxItem_DoubleClick(object sender, MouseButtonEventArgs e)
{
var listBoxItem = sender as ListBoxItem;
if (listBoxItem != null)
{
var content = listBoxItem.Content as string;
MessageBox.Show(content);
}
}
}
}
Here is a link to the MSDN page that explains a bit about EventSetters:
http://msdn.microsoft.com/en-us/library/system.windows.eventsetter.aspx

Accessing dependency property in the same control xaml

In a Wpf Application i have a main window.
I have added a user control to the same project.
In the user control's .xaml.cs file a Dependency property ( "Value" name of the property ) is added.
I would like to access the defined dependency property in the usercontrol.xaml.
I know i can do the same while creating the control instance either in window.xaml or some other user control.
But is it possible to access the dependency property defined in .xaml.cs in .xaml?
Question updated based on Vivs answer
Ok. I mentioned my question wrongly. Nevertheless even i was not aware of accessing. But my actual intended question is it possible to set the dependency property from .xaml. some thing like from the example given above,
<Grid CustomBackground ="{Binding Path= BackgroundColor}" />
Or
<Grid CustomBackground ="Blue" />
Is it possible to set the custom dependency properties like this in the same .xaml?
Yes it is possible.
something like:
.xaml
<UserControl x:Class="MvvmLight26.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmLight26"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:UserControl1}}, Path=CustomBackground}" />
</UserControl>
and .xaml.cs:
public partial class UserControl1 : UserControl {
public static readonly DependencyProperty CustomBackgroundProperty =
DependencyProperty.Register(
"CustomBackground",
typeof(Brush),
typeof(UserControl1),
new FrameworkPropertyMetadata(Brushes.Tomato));
public UserControl1() {
InitializeComponent();
}
public Brush CustomBackground {
get {
return (Brush)GetValue(CustomBackgroundProperty);
}
set {
SetValue(CustomBackgroundProperty, value);
}
}
}
Alternate:
If you say have the DataContext of the UserControl as itself like:
public UserControl1() {
InitializeComponent();
DataContext = this;
}
then in your xaml you could just go with:
<Grid Background="{Binding Path=DataContext.CustomBackground}" />
Update:
For the new question,
Not quite directly.
You can "set" the value if the custom DP is registered as an attached property(Do remember an attached property is not the same as a normal DP in it's behavior and scope.)
If you want to keep it as a normal DP, then you can keep UserControl1 from the original answer same as it is(just the DP part. You need to remove the xaml part of it and make it a non-partial class in the code-behind) and then derive it to a new UserControl.
something like:
<local:UserControl1 x:Class="MvvmLight26.UserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmLight26"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
CustomBackground="Blue"
mc:Ignorable="d">
<Grid />
</local:UserControl1>
You can ofc name UserControl1 as something like "BaseUserControl" or so to make it obvious that it's not intended for direct usage.
You can set the value from the UserControl.Style in the same xaml as well.
xaml:
<UserControl x:Class="MvvmLight26.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmLight26"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Style>
<Style>
<Setter Property="local:UserControl1.CustomBackground"
Value="Blue" />
</Style>
</UserControl.Style>
<Grid Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:UserControl1}}, Path=CustomBackground}" />
</UserControl>

XAML - How to have global inputBindings?

I have a WPF application with several windows. I would like to define GLOBAL inputBindings.
To define LOCAL inputbindings, i just declare the input in Window.InputBindings or UserControl.InputBindings.
To define GLOBALs, I wish i could do the same with the Application class...
<Application
....>
<Application.InputBindings>
...
</Application.InputBindings>
If i have the same binding in 2 different windows, i have to code it twice. This doesn't meet D.R.Y.'s philosophy and i guess there is a better way...
EDIT : in his answer Kent Boogaart advices me to use Style. Unfortunately, i can't figure out how to define it. This is the code :
<Application.Resources>
<Style TargetType="Window">
<Setter Property="InputBindings">
<Setter.Value>
<Window.InputBindings>
<KeyBinding KeyGesture="Ctrl+M" Command="local:App.MsgCommand />
</Window.InputBindings>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
It raises an error : error MC3080: The Property Setter 'InputBindings' cannot be set because it does not have an accessible set accessor.
Is my style wrong?
Is there another solution?
Any ideas? thanks!
One solution is to use an Attached Property with a Style to set the InputBindings on all the controls of a given type in your application. Unfortunately, since you can't make a "catch-all" Style (that I know of, anyway), you'll have to create a Style for each control type on which you want to set the InputBindings (this shouldn't, however, be too many controls). Below is some sample code that shows how to do this:
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
public class MyAttached
{
public static readonly DependencyProperty InputBindingsProperty =
DependencyProperty.RegisterAttached("InputBindings", typeof(InputBindingCollection), typeof(MyAttached),
new FrameworkPropertyMetadata(new InputBindingCollection(),
(sender, e) =>
{
var element = sender as UIElement;
if (element == null) return;
element.InputBindings.Clear();
element.InputBindings.AddRange((InputBindingCollection)e.NewValue);
}));
public static InputBindingCollection GetInputBindings(UIElement element)
{
return (InputBindingCollection)element.GetValue(InputBindingsProperty);
}
public static void SetInputBindings(UIElement element, InputBindingCollection inputBindings)
{
element.SetValue(InputBindingsProperty, inputBindings);
}
}
}
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:WpfApplication1"
StartupUri="Window1.xaml">
<Application.Resources>
<Style TargetType="TextBox">
<Setter Property="loc:MyAttached.InputBindings">
<Setter.Value>
<InputBindingCollection>
<KeyBinding Key="A" Modifiers="Ctrl" Command="loc:Window1.MyAction" />
</InputBindingCollection>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Button">
<Setter Property="loc:MyAttached.InputBindings">
<Setter.Value>
<InputBindingCollection>
<KeyBinding Key="A" Modifiers="Ctrl" Command="loc:Window1.MyAction" />
</InputBindingCollection>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
</Application>
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
<CommandBinding Command="loc:Window1.MyAction" Executed="MyAction_Executed" />
</Window.CommandBindings>
<StackPanel>
<Button Content="Try Ctrl+A Here!" />
<TextBox Text="Try Ctrl+A Here!" />
</StackPanel>
</Window>
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
public partial class Window1
{
public static readonly RoutedUICommand MyAction = new RoutedUICommand("MyAction", "MyAction", typeof(Window1));
public Window1() { InitializeComponent(); }
private void MyAction_Executed(object sender, ExecutedRoutedEventArgs e) { MessageBox.Show("MyAction!"); }
}
}
You could create a Style that is applied to all your Windows. That Style could set the InputBindings.

Resources