I want my TransitionFrame's backgound to be white, other then black, as is by default.
I have added the following style declaration on the PhoneApplicationPage:
<Style TargetType="toolkit:TransitionFrame">
<Setter Property="Background" Value="White"/>
</Style>
How do I force the transition frame to use my style, that is defined in each page separately?
In App.xaml.cs, in InitializePhoneApplication:
RootFrame = new TransitionFrame();
RootFrame.Background = new SolidColorBrush(Colors.White);
In the same way, if you have more properties, and want to use a style, you could probably use
RootFrame = new TransitionFrame();
RootFrame.Style = (Style) Current.Resources["MyStyle"];
Edit: Might've misread the question, if you want a custom style per page (I don't judge :p) then you can access the rootframe by adding static to your RootFrame declaration:
public static TransitionFrame RootFrame { get; private set; }
and elsewhere, simply using App.RootFrame.<property>
Related
Usual WPF architecture:
public partial class MainWindow: Window {
... InitializeComponent()
}
XAML: <Window x:Class="MainWindow"> </Window>
What I want to move to:
public abstract class BaseWindow: Window {
public System.Windows.Controls.TextBlock control1;
public System.Windows.Shapes.Rectangle control2;
public System.Windows.Controls.TextBox control3;
}
public partial class AWindowImplementation {
... InitializeComponent()
}
public partial class AnotherWindowImplementation{
... InitializeComponent()
}
XAML:
<BaseWindow x:Class="AWindowImplementation"> </BaseWindow>
<BaseWindow x:Class="AnotherWindowImplementation"> </BaseWindow>
The above is pseudo-code. This new architecture compiles, with warnings that the implementations hide the control defintions (because the place where I should put the 'override' keywords are withing the auto-generated InitializeComponent). Unfortunately the control fields don't get populated.
Is this achievable? What I am trying to do is create several UI designs with the same interface/controls so that the rest of the code can interact with either design.
EDIT: Thanks to pchajer and Yevgeniy, I now have the following working solution, but I still get override warnings:
public class MainWindowBase : Window
{
public TextBlock control1;
public Rectangle control2;
public TextBox control3;
static MainWindowBase()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MainWindowBase),
new FrameworkPropertyMetadata(typeof(MainWindowBase)));
}
public override void OnApplyTemplate()
{
control1 = (TextBlock) FindName("control1");
control2 = (Rectangle) FindName("control2");
control3 = (TextBox) FindName("control3");
}
}
<Style TargetType="{x:Type views:MainWindowBase}"
BasedOn="{StaticResource {x:Type Window}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type views:MainWindowBase}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
public partial class AWindowImplementation :MainWindowBase {
... InitializeComponent()
}
<MainWindowBase x:Class="AWindowImplementation"> </MainWindowBase>
I guess I will have to use different field names in the base class to get rid of the warnings, or perhaps remove InitializeComponent in the derived class. But anyway it works now.
In WPF you can create a Base class which inherits from Window and that has a XAML. But there is a workground
refer this link - How to create a common WPF base window style?
I'm not sure how you would expect that pseudo-code to work as nothing is calling your InitializeComponent. Ordinarily, WPF calls it on your behalf in your window's constructor. But in your case you're adding a new implementation (not an override) and nothing is calling it.
One option is to just call your new implementation from each subclass constructor. eg. AWindowImplementation's constructor could call this.InitializeComponent().
Another option is for BaseWindow to define a virtual method (say, InitializeComponentCore) that its constructor calls. Base classes can then override that method.
You need to define base class for Window as a custom control. Just create a new custom control, set base class to Window and then insert style from blend (you may add yours components). See also answer from pchajer.
I've found numerous sites that provide examples of how to add a custom spellchecking dictionary to an individual textbox like so:
<TextBox SpellCheck.IsEnabled="True" >
<SpellCheck.CustomDictionaries>
<sys:Uri>customdictionary.lex</sys:Uri>
</SpellCheck.CustomDictionaries>
</TextBox>
And I've tested this in my app and it works just fine.
However, I have industry specific jargon that I need to have ignored across ALL the textboxes in the application and applying this custom dictionary to each one individually seems to spit in the face of styles. At the moment I have a global textbox style to turn on spellchecking:
<Style TargetType="{x:Type TextBox}">
<Setter Property="SpellCheck.IsEnabled" Value="True" />
</Style>
I tried to do something like this to add the custom dictionary, but it doesn't like it, since the SpellCheck.CustomDictionaries is read only and setters only take writable properties.
<Style TargetType="{x:Type TextBox}">
<Setter Property="SpellCheck.IsEnabled" Value="True" />
<Setter Property="SpellCheck.CustomDictionaries">
<Setter.Value>
<sys:Uri>CustomSpellCheckDictionary.lex</sys:Uri>
</Setter.Value>
</Setter>
</Style>
I have done extensive searches looking for the answer to this, but all examples show only the one-use scenario in the specific textbox as cited in the first code block. Any help is appreciated.
I had the same issue and couldn't solve it with a style but created some code that accomplished the job.
First, I created a method to find all the textboxes contained within the visual tree of a parent control.
private static void FindAllChildren<T>(DependencyObject parent, ref List<T> list) where T : DependencyObject
{
//Initialize list if necessary
if (list == null)
list = new List<T>();
T foundChild = null;
int children = VisualTreeHelper.GetChildrenCount(parent);
//Loop through all children in the visual tree of the parent and look for matches
for (int i = 0; i < children; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
foundChild = child as T;
//If a match is found add it to the list
if (foundChild != null)
list.Add(foundChild);
//If this control also has children then search it's children too
if (VisualTreeHelper.GetChildrenCount(child) > 0)
FindAllChildren<T>(child, ref list);
}
}
Then, anytime I open a new tab/window in my application I add a handler to the loaded event.
window.Loaded += (object sender, RoutedEventArgs e) =>
{
List<TextBox> textBoxes = ControlHelper.FindAllChildren<TextBox>((Control)window.Content);
foreach (TextBox tb in textBoxes)
if (tb.SpellCheck.IsEnabled)
Uri uri = new Uri("pack://application:,,,/MyCustom.lex"));
if (!tb.SpellCheck.CustomDictionaries.Contains(uri))
tb.SpellCheck.CustomDictionaries.Add(uri);
};
In WPF XAML there is the convenient DesignHeight and DesignWidth, for instance in code as
<UserControl ... d:DesignHeight="500" d:DesignWidth="500" ... />
which is great because I can build the layout with a representative, but not locked-in, control size.
However, I'm often building dark UIs, where labels and so forth need to be white, but my controls still need a transparent background color. This creates a design-time inconvenience because white seems to be the default background color for transparent controls in the designer, leading to unreadable white-on-white labels.
Is there a way or strategy for setting the design-time background color, with similar convenience as DesignHeight/DesignWidth?
There's an undocumented property d:DesignStyle of type Style that you can set on a user control. This style is only applied in the designer and is not used at runtime.
You use it like this:
<UserControl ... d:DesignStyle="{StaticResource MyDesignStyle}" />
Or like this:
<UserControl ...>
<d:DesignerProperties.DesignStyle>
<Style TargetType="UserControl">
<Setter Property="Background" Value="White" />
<Setter Property="Height" Value="500" />
<Setter Property="Width" Value="500" />
</Style>
</d:DesignerProperties.DesignStyle>
</UserControl>
The Background property is what you asked for. The Height and Width do replace your d:DesignHeight=500 and d:DesignWidth=500 in the <UserControl> tag. Then you have all your design properties at one place.
Note however, that any value set on the Style property (the one used at runtime) will also override the DesignStyle in the designer.
I found that you can do one for yourself. Custom design-time attributes in Silverlight and WPF designer is a tutorial how to do it for both Silverlight and WPF.
My answer was found here: Black Background for XAML Editor. There are a number of choices including checking System.ComponentModel.DesignerProperties.GetIsInDesignMode(this) at runtime.
This is the complete solution for DesignBackground:
public class DesignTimeProperties : DependencyObject
{
private static readonly Type OwnerType = typeof(DesignTimeProperties);
#region DesignBackground (attached property)
public static Brush GetDesignBackground(DependencyObject obj)
{
return (Brush)obj.GetValue(DesignBackgroundProperty);
}
public static void SetDesignBackground(DependencyObject obj, Brush value)
{
obj.SetValue(DesignBackgroundProperty, value);
}
public static readonly DependencyProperty DesignBackgroundProperty =
DependencyProperty.RegisterAttached(
"DesignBackground",
typeof (Brush),
OwnerType,
new FrameworkPropertyMetadata(Brushes.Transparent,
DesignBackgroundChangedCallback));
public static void DesignBackgroundChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (IsInDesignMode)
{
var control = d as Control;
var brush = e.NewValue as Brush;
if (control != null && brush != null)
{
control.Background = brush;
}
}
}
public static bool IsInDesignMode
{
get
{
return
((bool)
DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof (DependencyObject)).DefaultValue);
}
}
#endregion
}
Usage:
<UserControl ... infra:DesignTimeProperties.DesignBackground="Black" />
The d:DesignerProperties.DesignStyle technique shown on this page works great for applying a WPF design-time-only style to a single control, but it doesn't appear to work for a Style in a ResourceDictionary that would apply to all of the appropriately-typed controls or elements under the scope of the dictionary. Below is simple solution I found for deploying a designer-only style into a ResourceDictionary.
Consider for example a Window containing a TreeView, where we want the TreeViewItem nodes to show as fully expanded—but only at design time. First, put the desired style in the XAML dictionary in the normal way.
<Window.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
</Style>
</Window.Resources>
Here, the Style is put in the ResourceDictionary of the Window but of course you could use any other subsuming dictionary instead. Next, in the C# code, remove the style from the ResourceDictionary when design mode is not detected. Do this is in the OnInitialized override:
protected override void OnInitialized(EventArgs e)
{
if (DesignerProperties.GetIsInDesignMode(this) == false)
Resources.Remove(typeof(TreeViewItem));
base.OnInitialized(e);
}
Design Mode: Runtime Mode:
I was going to create a Style for MapPolygon, but I can't seem to add a Setter for anything other than the properties inherited from Control, which doesn't help very much since the MapPolygon doesn't actually use many of those properties.
I mainly want to be able to style the Fill, Stroke, and StrokeThickness properties. When I try to do this, however, I get the following error: "Object reference not set to an instance of an object". Am I correct in thinking this is because the properties that I am trying to style are not dependency properties (DependencyProperty)?
If my thinking here is indeed correct, would the easiest way to solve this problem be to create a custom MapPolygon control and create dependency properties for Fill, Stroke, and StrokeThickness?
Let me know if I need to clarify something.
Update:
public class StyledMapPolygon : MapPolygon {
public static readonly DependencyProperty FillProperty =
DependencyProperty.Register("Fill", typeof(Brush), typeof(StyledMapPolygon),
new PropertyMetadata(new SolidColorBrush(), new PropertyChangedCallback(OnFillChanged)));
private static void OnFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
StyledMapPolygon instance = (StyledMapPolygon) d;
instance.Fill = e.NewValue as Brush;
}
}
.
<Style x:Key="CustomStyle" TargetType="exts:StyledMapPolygon">
<Setter Property="Fill" Value="{StaticResource BuildingFillBrush}" />
</Style>
This is just a simplified version of a style that I would like to use. the StyledMapPolygon is a object I created inherited from MapPolygon. The only difference is that I created a DependencyProperty for "Fill" that just maps to the base property.
The error mentioned above still appears on "Fill" within the Setter, but it now works (displays correctly on the phone). I can live with the error there since it still runs, but I would very much like to have my app be error free.
Yes, a property must be a DependencyProperty in order to be set by a style.
There's nothing wrong with adding your own dependency property that wraps a property on the base class, but I wouldn't recommend trying to use the same property name. Create a differently named property, with property changed handler which relays the value which is set to the underlying property.
Of course if the "error" you mention is Intellisense there's really no reason to care, so long as code compiles and runs.
How can I define one global GridViewColumnHeader.Click handler for any ListView.GridViewColumnHeader in my project?
I mean is it possible to set a Style or a Template in app.xaml for TargetType=GridViewColumnHeader so any columnheader in any listview in the project would response to the method in app.xaml.cs?
Though it isn't a global event handler, I would simply create a new control that inherits from ListView and implement the Click handler there.
Yes, with one caveat: You can create a Style that applies to all GridViewColumnHeaders, but you cannot set the Click event in it. However you can set the Command property which has almost exactly the same result:
<Application.Resources>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Command"
Value="{x:Static local:GridViewClickHandler.ClickCommand}" />
</Style>
...
Now it is only required to create the command, register a class handler, and write the code to handle it:
public GridViewClickHandler
{
public RoutedCommand ClickCommand;
static GridViewClickHandler()
{
ClickCommand = new RoutedCommand("ClickCommand", typeof(GridViewClickHandler));
CommandManager.RegisterClassCommandBinding(
typeof(GridViewColumnHeader),
new CommandBinding(ClickCommand, OnColumnHeaderClick));
}
static void OnColumnHeaderClick(object sender, ExecutedRoutedEventArgs e)
{
// your code here
}
}
Note that if you manually set the GridViewColumnHeader's Command property anywhere else in your application it will take precedence over the style. If this is a concern, you may want to instead catch tunneling PreviewMouseDown events at your Window and check each to see if it's original source is a GridViewColumnHeader.