Set default text for textbox in WPF - wpf

I need all my textboxes to have a default text so I have done what is explained in this another post. I have used the solution proposed by Steve Greatrex and marked as accepted.
It is working for me but now I am trying to improve it to use in multiple textboxes as a template but for each of my textboxes I want to set a custom different default text.
As template default text is set to whatever, for example "Your Prompt Here" in above link, then all the textboxes I bind this template will have the same text.
I would like to put a different default text for each of my textboxes so how can I do it using the same controltemplate for all the textboxes?
Under "Windows.Resources" I have created an style that cotains the template indicated in the above post:
<Style x:Key="DefaultText" TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<!-- here the controltemplate from the above post -->
</Setter.Value>
</Setter>
</Style>
and I use it in my textboxes in the following way:
<TextBox Style="{StaticResource DefaultText}"/>

Use custom attached property instead of the Tag which has no any specific semantic:
public static class TextBoxHelper
{
public static readonly DependencyProperty DefaultTextProperty = DependencyProperty.RegisterAttached(
"DefaultText",
typeof(string),
typeof(TextBoxHelper));
[AttachedPropertyBrowsableForType(typeof(TextBox))]
public static string GetDefaultText(FrameworkElement element)
{
return (string)element.GetValue(DefaultTextProperty);
}
public static void SetDefaultText(FrameworkElement element, string value)
{
element.SetValue(DefaultTextProperty, value);
}
}
Then you can use it from XAML:
xmlns:helpers="<your_namespace_with_helpers>"
<TextBox helpers:TextBoxHelper.DefaultText="..."/>
Then in your ControlTemplate you can set Text like this:
Text="{Binding Path=(helpers:TextBoxHelper.DefaultText), RelativeSource={RelativeSource TemplatedParent}}"
Although this approach is more verbose than using the Tag property I recommend you to use it because:
If your code will be maintained by someone else it will be quiet unexpected for this person that control relies on Tag property which can contain anything since its type is object.
DefaultText attached property has strict semantic. Anyone can say what it needed for just looking on its name and type.
Rule of thumb is always try to avoid using of properties with undefined semantic.

I have solved it by replacing Text property in textblock within control template by this one:
Text="{TemplateBinding Tag}"
then I call it from any textbox like below:
<TextBox Style="{StaticResource WatermarkedTextBox}"
Tag="Type whatever here" />
You can choose default text for each textbox by specifying the Tag property.
Also, this solution does not require the aero theme.
The solution that Clemens propose in this link also works and it is based on aero theme.

Related

Apply default Button style to custom Button class

I've created a custom IconButton class that inherits from Button and adds a few dependency properties to place an image in front of the button's text.
The code begins like this:
public partial class IconButton : Button
{
// Dependency properties and other methods
}
It comes with a XAML file that looks like this:
<Button x:Class="Unclassified.UI.IconButton" x:Name="_this" ...>
<Button.Template>
<ControlTemplate>
<Button
Padding="{TemplateBinding Padding}"
Style="{TemplateBinding Style}"
Focusable="{TemplateBinding Focusable}"
Command="{TemplateBinding Button.Command}">
<StackPanel ...>
<Image .../>
<ContentPresenter
Visibility="{Binding ContentVisibility, ElementName=_this}"
RecognizesAccessKey="True"
Content="{Binding Content, ElementName=_this}">
<ContentPresenter.Style>
...
</ContentPresenter.Style>
</ContentPresenter>
</StackPanel>
</Button>
</ControlTemplate>
</Button.Template>
</Button>
That works well so far. (But if you know a simpler way to override a Button's content without changing the entire template and placing a Button within the Button, please let me know. Every time I tried, Visual Studio 2010 SP1 immediately crashed the moment I closed the final XML tag.)
Now I've added some code to fix WPF's broken Aero2 theme for Windows 8. It's a separate ResourceDictionary that overwrites all sorts of default styles: (Based on this, via here)
<ResourceDictionary ...>
<Style TargetType="{x:Type Button}">
...
</Style>
</ResourceDictionary>
The new ResourceDictionary is added to the Application Resources on startup, in App.xaml.cs:
protected override void OnStartup(StartupEventArgs args)
{
base.OnStartup(e);
// Fix WPF's dumb Aero2 theme if we're on Windows 8 or newer
if (OSInfo.IsWindows8OrNewer)
{
Resources.MergedDictionaries.Add(new ResourceDictionary
{
Source = new Uri("/Resources/RealWindows8.xaml", UriKind.RelativeOrAbsolute)
});
}
...
}
This also works well for normal Button controls I place in my XAML views. (I'm still looking for a method to find out the real Windows theme instead of relying on the version number.)
But my IconButton control doesn't consider these new defaults and is still based on WPF's built-in Button style which is very basic. (It's really just a tight rectangle without all the details and interactivity that Win32 shows.)
I guess I need a way to tell my IconButton that it should re-evaluate the base style and see the newly added RealWindows8 styles. How can I do that?
I found the solution. There are two ways to accomplish this. Either one is sufficient.
The XAML way:
Add the Style attribute to the derived control. This presets the new control's style explicitly to whatever has been defined in the application as the Button style. StaticResource is sufficient for this. If a different Style is specified where the derived control is used, that will replace this initial value.
<Button Style="{StaticResource {x:Type Button}}" ...>
...
</Button>
The code(-behind) way:
Call the SetResourceReference method in the constructor of the derived class.
public IconButton()
{
// Use the same style as Button, also when it is overwritten by the application.
SetResourceReference(StyleProperty, typeof(Button));
...
}
I've tested this for my IconButton as well as a derived TabControl and TabItem class.
(Source)

Change Default Binding/Textbox StringFormat in xaml

I am creating a form with a lot of textboxes that have text attributes as declared below:
Text="{Binding Path=SomeField, StringFormat='\{0:#,##0.##\}', Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true, Source={StaticResource statementsMainsViewSource}}"
In order to save bulk space & keystrokes, I want to know if there is a way to setup default textboxes in each window using styles (eg somewhat similar to the incorrect code below):
<Style TargetType="{x:Type TextBox}">
<Setter Property="StringFormat" Value="\{0:#,##0.##\}" />
</Style>
Unfortunately, it's the binding stuff that has the property, not the text box, and i don't know how to set a binding style.
Can anyone point me to the correct syntax for changing default binding StringFormats - or can anyone suggest how I can do what I'm trying?
cheers and tia
mcalex
Try this
public class TextBinding:Binding
{
public TextBinding()
{
Mode = BindingMode.TwoWay;
StringFormat = #"\{0:#,##0.##\}";
ValidatesOnExceptions = true;
NotifyOnValidationError = true;
}
}
xmlns:myBinding="clr-namespace:WpfApplication2">
<Grid>
<TextBox Text="{myBinding:TextBinding Path=SomeProperty}"/>
</Grid>
Now you can Bind this way to all Textboxes without setting the above 4 properties of binding they will be automatically applied. I hope this will help you to get an idea.

How to allow user to change property in a template?

I have a button which in Blend I have edited (using Edit current template). I have added my animations for mouse over etc and the button works as expected.
However, on the mouse over event I have a shape that scales. What I want to do is give the user the option to set in XAML the rotation and scaling properties.
So for example, something like this:
<Button Height="76" Content="Gallery" Style="{StaticResource RotatingAnimationButton}" " Scaling="2.0" >
where in the template I have :
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Document" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].
(ScaleTransform.ScaleX)">
where Value="1.5" would be changed to "2.0".
Currently, all I have is the style of the template. I am not sure whether I can pass in the parameters or I have to create some sort of user control?
JD
Note : This question was originally posted as Silverlight and WPF. But as you will see it only applies to Silverlight which is why the excellent solutions provided caused me problems.
You have two good options:
You can subclass Button and add a "Scaling" property, or
You can create an attached "Scaling" property and attach it to Button
In either case, your animation can bind to it.
Unless your button is custom in other ways, I would generally go with the attached property. You would use a standard attached property template (use the "propa" snippet):
public class MyAttachedProperties
{
// Scaling
public static double GetScaling(DependencyObject obj) { return (double)obj.GetValue(ScalingProperty); }
public static void SetScaling(DependencyObject obj, double value) { obj.SetValue(ScalingProperty, value); }
public static readonly DependencyProperty ScalingProperty = DependencyProperty.RegisterAttached("Scaling", typeof(double), typeof(MyAttachedProperties));
}
In the code that uses the button you would reference it like this:
<Button Height="76" Content="Gallery"
Style="{StaticResource RotatingAnimationButton}"
local:MyAttachedProperties.Scaling="2.0" />
In the template you would bind it like this:
Value="{Binding Path=(local:MyAttachedProperties.Scaling),
RelativeSource={RelativeSource TemplatedParent}}"
Both of these bits of XAML assume you have xmlns:local defined to include the MyAttachedProperties class.

WPF: How do I create a button "template" that applies a style & has an image in it?

There are multiple places in my WPF application where I need a button that looks & feels like a regular button, but:
It shows a specific icon on it (defined as {StaticResource EditIcon})
It applies a style (defined as {StaticResource GrayOutButtonStyle})
I would prefer to define these attributes in a single location, rather than repeating them each place the button is used. What is the appropriate way to do this in XAML?
--
If it helps, below is what I'm currently doing, but I was told this is wrong:
Updated: Is this the wrong way? Is there a way to fix this so that it is the "right way"?
I define the button as a template with the key EditButton:
<ControlTemplate x:Key="EditButton" TargetType="{x:Type Button}">
<Button Style="{StaticResource GrayOutButtonStyle}"
Command="{TemplateBinding Command}">
<Image x:Name="editImage" Source="{StaticResource EditIcon}" />
</Button>
</ControlTemplate>
Then, I declare a button with the template EditButton each place I want to use it in the application. I also indicate the Command to invoke here:
<Button Template="{StaticResource EditButton}" Command="..." />
Is this not right? What would be the correct way to do this?
A different approach:
Have you considered making a custom control? This way, you can create your own attributes to set the image contained in the button, and don't have to rely on multiple styles.
<myControl:MyButton x:Name="oneButton" ImageSource="MyButton.png" />
<myControl:MyButton x:Name="anotherButton" ImageSource="MyOtherButton.png" />
class MyButton {
private string imageSource;
public string ImageSource {
get {
return this.imageSource;
}
set {
this.imageSource = value;
//set the image control's source to this.imageSource
}
}
}
You can create a Style which targets all the Button of your app. Do do that, simply create a Style without giving it a Key:
<Style TargetType={x:Type Button}>
</Style>
Then in the Style, you can add a setter which sets the Template property:
<Setter Property="Template">
<Setter.Value>
<!-- whatever you want -->
</Setter.Value>
</Setter>

Create TabItems with differing content at runtime based on templates in WPF

I'm writing an application with WPF and part of it involves managing for the user various files which are used configure custom, in-house devices. I need to be able to manipulate different types of configurations in tabs in the same TabControl, meaning that the content of the TabItems must be dynamically generated. I'd like to do this with ControlTemplates, but I haven't been successful in getting a working template yet. I have a ControlTemplate called "pendantConfigurationTabItemTemplate" defined in my Window resources, and I use the following code to apply the template (which contains a named item I need to access) to the TabItems and add them to their parent TabControl :
<ControlTemplate x:Key="pendantConfigurationTabItemTemplate" TargetType="TabItem">
<StackPanel Orientation="Vertical">
<my:PendantConfigurationFileEditor x:Name="configurationEditor"/>
<StackPanel Style="{StaticResource defaultOkCancelButtonsContainerStyle}">
<Button Style="{StaticResource defaultOkCancelButtonStyle}"/>
<Button Style="{StaticResource defaultOkCancelButtonStyle}" Click="OkButton_Click"/>
</StackPanel>
</StackPanel>
</ControlTemplate>
Code behind :
TabItem ConfigTab = new TabItem();
switch (ConfigFile.Device)
{
case DeviceType.PENDANT:
{
ControlTemplate TabTemplate = Resources["pendantConfigurationTabItemTemplate"] as ControlTemplate;
ConfigTab.Template = TabTemplate;
ConfigTab.ApplyTemplate();
object Editor = TabTemplate.FindName("configurationEditor", ConfigTab);
PendantConfigurationFileEditor ConfigFileEditor = Editor as PendantConfigurationFileEditor;
ConfigFileEditor.PendantConfiguration = DeviceConfig;
break;
}
default:
/* snipped */
return;
}
ConfigTab.Header = ConfigFile.ConfigurationName;
this.EditorTabs.Items.Add(ConfigTab);
this.EditorTabs.SelectedIndex = this.EditorTabs.Items.Count - 1;
However, whenever I run the program, no tabs get added to the tab control, instead the tab control (seemingly) gets replaced or covered by the content of the template. Can somebody please help me out with this ?
Effectively, what I want to do is use the WPF templates as TabItem factories
TabControl.ItemsSource plus DataTemplates is effectively the "templates as factories" solution you are asking for, but it demands a slightly different approach to your current one.
Rather than writing procedural code to create and template TabItems and calling Items.Add, use the ItemsSource property and data binding. This will cause WPF to create a TabItem for each object in the ItemsSource. You can then use ContentTemplateSelector to select appropriate templates for the object displayed on this tab, according to whatever criteria are appropriate (e.g. the Device property) -- though in this case you will be using DataTemplates rather than ControlTemplates.
Your selector will look something like this:
public class DeviceTypeSelector : DataTemplateSelector
{
public DataTemplate PendantTemplate { get; set; }
public DataTemplate DefaultTemplate { get; set; }
public override SelectTemplate(object item, DependencyObject container)
{
ConfigFile cf = (ConfigFile)item;
switch (cf.Device)
{
case DeviceType.Pendant: return PendantTemplate;
default: return DefaultTemplate;
}
}
}
and will be instantiated in XAML like this:
<local:DeviceTypeSelector x:Key="dts"
PendantTemplate="{StaticResource pt}"
DefaultTemplate="{StaticResource dt}" />
(where pt and dt are suitable DataTemplates defined elsewhere in the resources).
Finally, your TabControl will look like this:
<TabControl Name="EditorTabs"
ContentTemplateSelector="{StaticResource dts}" />
and you set it up as EditorTabs.ItemsSource = myConfigFiles; (or better still let it acquire the ItemsSource in XAML from the DataContext).
You'll also want to set up the headers of the TabItems: to do this, use TabControl.ItemContainerStyle, with a Setter for the Header property. I think this would look something like this:
<TabControl ...>
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding ConfigurationName}" />
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
(You can also inline the ContentTemplateSelector, by the way: I broke it out into a resource mostly so as to show things in smaller chunks.)

Resources