NumericUpDown - Focus not set - wpf

I am using NumericUpDown control (from WPFs extended toolkit Version 2.9) and I am trying to set focus on it via attached property.
My XAML
<xctk:DecimalUpDown FormatString="F5"
wbui:FocusExtension.IsFocused="{Binding Path=IsFocusedMenge, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Value="{Binding Path=Menge, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
/>
Here my FocusExtensiion.IsFocues
private static void IsFocusedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var fe = (FrameworkElement)d;
if (e.OldValue == null)
{
fe.GotFocus += FrameworkElement_GotFocus;
fe.LostFocus += FrameworkElement_LostFocus;
}
if (!fe.IsVisible)
{
fe.IsVisibleChanged += new DependencyPropertyChangedEventHandler(FrameworkElement_IsVisibleChanged);
}
if ((bool)e.NewValue)
{
fe.Focus(); // will be called
}
}
When i set my Property IsFocusedMenge to true, then the focus will not be set. The code line fe.Focus() will be called when I set a Breakpoint there.
I found another topic here (How to set focus on NumericUpDown control?), but when I set this attribute Focusable=true, I will get an StackOverFlowException when calling the fe.Focus() method.
Any ideas? Thx.
Update
Also tried it with adding an event to the grid, to set the focus in the View/UserControl ... but without success.
private void GridMenge_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
this.Menge.Focus();
}
}
Focus is still not set (Property Focusable set to True/False - no changes)

I got some information from the official support.
This is already fixed. The fix is included in v3.1.
(You can see the discussion thread here: https://wpftoolkit.codeplex.com/discussions/658785)
To fix it, go in file:
Xceed.wpf.Toolkit/NumericUpDown/Themes/Aero2.NormalColor.xaml
(for Windows8 and up)
Xceed.wpf.Toolkit/NumericUpDown/Themes/Generic.xaml
(for other Windows)
In the style for "NumericUpDown"
a) Replace
<Setter Property="Focusable" Value="False" />
with
<Setter Property="IsTabStop" Value="False" />
b) In the "PART_TextBox"
replace
IsTabStop="{TemplateBinding IsTabStop}"
with
IsTabStop="True"

Related

WPF MVVM: Strange Binding behavior

I have a UserControl that contains a TabControl.
<UserControl x:Class="Test.MyUC"
....
xmlns:vm="clr-namespace:Test.ViewModels"
xmlns:ikriv="clr-namespace:IKriv.Windows.Controls.Behaviors"
...
<UserControl.Resources>
<vm:MyUCVM x:Key="VM" />
</UserControl.Resources>
<UserControl.DataContext>
<StaticResourceExtension ResourceKey="VM" />
</UserControl.DataContext>
<!-- Using Ivan Krivyakov's Attached Behavior -->
<TabControl ikriv:TabContent.IsCached="True"
TabStripPlacement="Top" ItemsSource="{Binding TabList}" IsSynchronizedWithCurrentItem="True">
<TabControl.Resources>
<DataTemplate DataType="{x:Type vm:MyTab1VM}">
<v:MyTab1/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:MyTab2VM}">
<v:MyTab2/>
</DataTemplate>
</TabControl.Resources>
...
Of course, in MyUCVM, I have TabList. Now, up to this point, everything works fine.
The problem starts when one of the tabs (e.g. MyTab1) in the TabControl needs to continuously and recursively read data from some external source (done in the ViewModel of course), and pass that data to View (via Binding) to display. Even up to this point everything is working. However, I do not want that to run when the tab is not visible, because there is no point to do that.
To do that, MyTab1VM needs to know if the associated View (MyTab1) is the selected tab. Therefore, I wired this up:
MyTab1:
<Style TargetType="TabItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=OneWayToSource}" />
</Style>
MyTab1VM
public static readonly DependencyProperty IsSelectedProperty =
DependencyProperty.Register("IsSelected",
typeof(bool),
typeof(MyTab1VM),
new PropertyMetadata(false, new PropertyChangedCallback(IsSelectedChanged))
);
public bool IsSelected
{
get
{
return (bool) GetValue(IsSelectedProperty);
}
set
{
SetValue(IsSelectedProperty, value);
}
}
public static void IsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.Property == IsSelectedProperty)
{
MyTab1VM vm = d as MyTab1VM ;
vm.SetupToGetData();
}
}
private void SetupToGetData()
{
if (this.IsSelected)
{
System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(100);
timer.Tick += timer_Tick;
timer.Start();
}
}
private void timer_Tick(object sender, EventArgs e)
{
if (this.IsSelected)
this.MyData = ExternalSource.GetData();
else
{
(sender as System.Windows.Threading.DispatcherTimer).Stop();
}
}
Unfortunately, this setup only works when I set this.IsSelected = true; manually in the MyTab1VM's constructor. Leaving that out in the constructor, the data do not get shown in the view.
I have set breakpoints and confirmed that the binding for IsSelected is running correctly. Even the timer is running, and ExternalSource.GetData() is being called. But this.MyData = ExternalSource.GetData(); is not triggering the change from the ViewModel to the View.
The most puzzling part is that the same binding is triggered if IsSelected is set to true from the constructor.
Anyone out there knows what happened here?
I managed to do some fruitful troubleshooting on my own. I made a breakpoint in SetupToGetData() and I put this.GetHashCode() in my debugging watchlist. When I manually set this.IsSelected = true in the constructor, I realized that the SetupToGetData() method is called twice, with two different hash values. Planting another breakpoint in the constructor also showed that the constructor is called when I switch to this tab.
I have decided to move this to a new question, because it looks highly possible that the problem has nothing to do with binding.
Edit
Seems like I was right that this is the root of this problem. As that question is solved, so is this as well.

Design-time-only background color in WPF?

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 Resource­Dict­ionary 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:

Silverlight DataTrigger not firing on load

I'm attempting to convert some of my WPF skills to Silverlight, and have run into a slightly odd problem in the test mini-app I've been working on. In WPF, I got used to using DataTriggers within a style to set up control properties based on properties of the bound data. I discovered that some assemblies related to Blend allow you to do something like this in Silverlight, and I came up with something like this, in which I've got the following namespaces declared:
xmlns:ia="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
xmlns:iv="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<DataTemplate x:Key="testItemTemplate">
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Name, Mode=TwoWay}" x:Name="thing"/>
<iv:Interaction.Triggers>
<ia:DataTrigger Binding="{Binding Name}" Value="ReddenMe" Comparison="Equal">
<ia:ChangePropertyAction TargetName="thing" PropertyName="Foreground" Value="Red">
</ia:ChangePropertyAction>
</ia:DataTrigger>
</iv:Interaction.Triggers>
</StackPanel>
</DataTemplate>
In this example, I've got a data object implementing INotifyPropertyChanged and raising the PropertyChanged event as usual for the Name property. I get the expected behaviour if I change the value of the textbox and lose focus, but if the initial value of the textbox is set to ReddenMe (which for this contrived example I'm using as the trigger for the text to be red), the text doesn't go red. Does anybody know what's going on here? For DataTriggers in WPF, the trigger would be fired immediately for any data.
I realise that I could use a Converter here, but I can think of situations where I'd want to use triggers, and I wonder if there's anything I could do to make this work.
Here's a solution I found on Tom Peplow's blog: inherit from DataTrigger, and make the trigger evaluate the condition when its associated element is loaded.
Here's how you can code it:
public class DataTriggerEvaluateOnLoad : Microsoft.Expression.Interactivity.Core.DataTrigger
{
protected override void OnAttached()
{
base.OnAttached();
var element = AssociatedObject as FrameworkElement;
if (element != null)
{
element.Loaded += OnElementLoaded;
}
}
protected override void OnDetaching()
{
base.OnDetaching();
var element = AssociatedObject as FrameworkElement;
if (element != null)
{
element.Loaded -= OnElementLoaded;
}
}
private void OnElementLoaded(object sender, RoutedEventArgs e)
{
EvaluateBindingChange(null);
}
}

WPF DependencyProperty... now it works... now it doesn't... how come?

I have a ClockFace UserControl that exposes a number of properties to enable users to style it. The clock has two Ellipse objects as borders; an outer border and an inner border.
<Ellipse Name="OuterBorder" Panel.ZIndex="5" StrokeThickness="{Binding BorderOuterThickness}" Stroke="{Binding BorderOuteBrush}" />
<Ellipse Name="InnerBorder" Panel.ZIndex="6" StrokeThickness="{Binding BorderInnerThickness}" Margin="{Binding StrokeThickness, ElementName=OuterBorder}" Stroke="{Binding BorderInnerBrush}">
public static readonly DependencyProperty BorderInnerBrushProperty = DependencyProperty.Register("BorderInnerBrush", typeof(Brush), typeof(ClockFace), new
PropertyMetadata(new LinearGradientBrush(Color.FromRgb(118, 57, 57), Color.FromRgb(226, 185, 185), new Point(0.5, 0), new Point(0.5, 1))));
public Brush BorderInnerBrush
{
get { return (Brush)GetValue(BorderInnerBrushProperty); }
set { SetValue(BorderInnerBrushProperty, value); }
}
public static readonly DependencyProperty BorderOuterBrushProperty = DependencyProperty.Register("BorderOuterBrush", typeof(Brush), typeof(ClockFace), new
PropertyMetadata(new LinearGradientBrush(Color.FromRgb(226, 185, 185), Color.FromRgb(118, 57, 57), new Point(0.5, 0), new Point(0.5, 1))));
public Brush BorderOuterBrush
{
get { return (Brush)GetValue(BorderOuterBrushProperty); }
set { SetValue(BorderOuterBrushProperty, value); }
}
These can be set in a style and will update correctly when the styles are switched. I thought that I would be clever and add a shortcut property called BorderBrush that passes itself to the BorderOuterBrush property and then passes a copy of itself with its gradient reversed to the BorderInnerBrush property. To enable this code to run when the property was set after initialisation (by switching styles), I had to implement a PropertyChangedCallback method that calls the SetBorderBrushes method.
public new static readonly DependencyProperty BorderBrushProperty = DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(ClockFace), new
PropertyMetadata(OnBorderBrushChanged));
private static void OnBorderBrushChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
((ClockFace)dependencyObject).SetBorderBrushes((Brush)e.NewValue);
}
public new Brush BorderBrush
{
get { return (Brush)GetValue(BorderBrushProperty); }
set { SetValue(BorderBrushProperty, value); }
}
private void SetBorderBrushes(Brush brush)
{
if (brush != null)
{
BorderOuterBrush = brush;
Brush innerBrush = BorderOuterBrush.Clone();
if (brush.GetType() == typeof(LinearGradientBrush) || brush.GetType() == typeof(RadialGradientBrush))
{
foreach (GradientStop gradientStop in ((GradientBrush)innerBrush).GradientStops)
{
gradientStop.Offset = 1 - gradientStop.Offset;
}
}
BorderInnerBrush = innerBrush;
}
}
When the BorderBrush property is set in a style, it all works just fine... that is until I switch the style at run time. Now the strangest thing happens... let me explain.
I have four preset styles and individually, they all work just fine. Three of them use the two BorderInnerBrush and BorderOuterBrush properties and one uses the shortcut BorderBrush property. I can switch between the styles using a ContextMenu and some code behind that accesses the xaml styles from Resources and sets them to the ClockFace object's Style property.
I can switch between the three styles that don't use the shortcut property endlessly without problem. I can also switch to the style that does use the shortcut property and it appears just fine. This is when the strangeness begins.
After switching to the style that uses the BorderBrush property, the BorderInnerBrush and BorderOuterBrush properties simply stop working. The preset Brush objects set in the various styles no longer get set on the two Ellipse objects. I pluged in some PropertyChangedCallback methods to the inner and outer border properties to see what was going on.
When I first run the application, I can switch to the three styles that don't use the shortcut property without problem. I put breakpoints on all three border Brush properties' PropertyChangedCallback methods and debugged the program. When switching to each of these three styles, the inner and outer border properties' callback methods' breakpoints were hit as you would expect. When switching to the style that uses the BorderBrush property, its callback method's breakpoint was hit. The SetBorderBrushes method sets the two other border Brush objects so the inner and outer border properties' callback methods' breakpoints were then hit as you would expect.
Again, this is the weird part. When switching to any of the other three styles after this, the inner and outer border properties' callback methods' breakpoints are no longer hit at all. Instead, the breakpoint in the callback method attached to the BorderBrush property is hit an the value of e.NewValue is null. As null values are ignored in the SetBorderBrushes method, no further breakpoints are hit.
After further investigation, I discovered that the e.NewValue was null because there was no default value set on the BorderBrushProperty DependencyProperty. Indeed, after adding a default Brush object to the declaration, this is the Brush that would be passed in e.NewValue in the callback method. Although the breakpoints in the two inner and outer border properties' callback methods would get hit after this, it was only because they are set in the SetBorderBrushes method. The Brush objects set in the BorderInnerBrush and BorderOuterBrush objects in the styles never get passed to these properties after the BorderBrush property has been used once.
One final point to note is that just as the default value of the BorderBrushProperty property is set when a value is not explicitly set in a style, the default values of the inner and outer border DependencyProperty objects are also set when their values are not explicitly set in a style, but only when the BorderBrush property is not also set in the style.
I've been stuck on this for days now and although an easy solution would be to remove the shortcut property, I'd rather find out what's going on and fix it. I hope I've provided enough information for some bright spark to be able to solve this problem, so, if you have any ideas or questions, please share them. Many thanks.
UPDATE >>
Following Rick's suggestion, I created another pair of Brush properties and set them from the callback methods attached to the other three Brush properties. Using this setup, I could switch between all of the styles without any visual problems... or so I thought.
I can now switch from the style that uses the BorderBrush (shortcut) property to the styles that set the two BorderInner and BorderOuter properties and the borders update correctly, so thanks Rick for getting me one step closer. I still have a problem when switching from the style that sets the BorderBrush property to the style that does not explicitly set any border Brush.
Therefore, I still have the same problem that the BorderInnerBrush and BorderOuterBrush properties don't work directly after being set from code behind. What's new is that if I then switch to a style that sets the two Brush properties, this seems to 'wake them up' again... if I then switch to the style that sets no border Brush, the inner and outer properties set their default values correctly again.
It's only after using a style that sets the two border properties from code behind that they become dead to being set in styles or using their default values. This is so strange... can anyone work it out?
UPDATE 2 >>>
First, thanks so much for your time and example Rick. After copying and pasting Rick's example code into a new project, I had to make a few alterations before it would run... maybe because I don't have Expression Blend 4? I installed the SDK and added the references to the noted dlls, but had to use the following XML namespace declarations instead:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
I also had to change each ChangePropertyAction declaration slightly to:
<ei:ChangePropertyAction TargetName="clock" PropertyName="Style" Value="{StaticResource styleBrush}"/>
Then, it worked fine for me and is a good representation of that portion of my actual ClockFace control, with two exceptions. The first is that my styles are switched from code behind via an event handler - this is clearly not causing my problem. The second difference is that I have set default Brush values on my versions of ActualOuterBrush and ActualInnerBrush, so that users of the control don't have to supply border brushes.
So my final problem is that the default inner and outer border brushes do not get set in a Style with no border properties explicitly set after the BorderBrush property has been set in a Style. Remember, the default values do get set up until this point. So, I experimented with Rick's example and added some default values:
private static readonly DependencyPropertyKey ActualInnerBrushPropertyKey = DependencyProperty.RegisterReadOnly("ActualInnerBrush", typeof(Brush), typeof(Clock), new UIPropertyMetadata(Brushes.Teal));
private static readonly DependencyPropertyKey ActualOuterBrushPropertyKey = DependencyProperty.RegisterReadOnly("ActualOuterBrush", typeof(Brush), typeof(Clock), new UIPropertyMetadata(Brushes.Salmon));
Now this project has a similar problem... the default values are never reset. I'm so baffled by this behaviour.
I've spent so long stuck on this problem now and although I have learned a number of useful things from Rick, I still have this problem with the default values. I've decided that the simplest thing to do is to remove the shortcut BorderBrush property. Rick has helped so much that I am awarding his answer as the correct answer, but if anyone reading this can help with the default value, I'd be grateful to hear from them.
Once a property has been set, styles no longer will be applied. By setting the inner and outer brush properties in your changed handler yourself, the dependency property subsystem is not aware that the the change was actually due to a style versus you doing it explicitly.
One solution is to expose protected read-only ActualInnerBorderBrush and ActualOuterBorderBrush properties and then have all three of the user-definable properties set these actual values in their respective change handlers. This way the user-visible properties can always be "as set by the user" without interfering with each other.
Edit:
Here is a complete working implementation of the five properties:
public class Clock : StackPanel
{
public Brush Brush
{
get { return (Brush)GetValue(BrushProperty); }
set { SetValue(BrushProperty, value); }
}
public static readonly DependencyProperty BrushProperty =
DependencyProperty.Register("Brush", typeof(Brush), typeof(Clock),
new UIPropertyMetadata((d, e) => (d as Clock).OnBrushChanged(d, e)));
public void OnBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ActualInnerBrush = e.NewValue as Brush;
ActualOuterBrush = e.NewValue as Brush;
}
public Brush InnerBrush
{
get { return (Brush)GetValue(InnerBrushProperty); }
set { SetValue(InnerBrushProperty, value); }
}
public static readonly DependencyProperty InnerBrushProperty =
DependencyProperty.Register("InnerBrush", typeof(Brush), typeof(Clock),
new UIPropertyMetadata((d, e) => (d as Clock).OnInnerBrushChanged(d, e)));
public void OnInnerBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ActualInnerBrush = e.NewValue as Brush;
}
public Brush OuterBrush
{
get { return (Brush)GetValue(OuterBrushProperty); }
set { SetValue(OuterBrushProperty, value); }
}
public static readonly DependencyProperty OuterBrushProperty =
DependencyProperty.Register("OuterBrush", typeof(Brush), typeof(Clock),
new UIPropertyMetadata((d, e) => (d as Clock).OnOuterBrushChanged(d, e)));
public void OnOuterBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ActualOuterBrush = e.NewValue as Brush;
}
public Brush ActualInnerBrush
{
get { return (Brush)GetValue(ActualInnerBrushProperty); }
private set { SetValue(ActualInnerBrushPropertyKey, value); }
}
private static readonly DependencyPropertyKey ActualInnerBrushPropertyKey =
DependencyProperty.RegisterReadOnly("ActualInnerBrush", typeof(Brush), typeof(Clock), new UIPropertyMetadata());
public static readonly DependencyProperty ActualInnerBrushProperty = ActualInnerBrushPropertyKey.DependencyProperty;
public Brush ActualOuterBrush
{
get { return (Brush)GetValue(ActualOuterBrushProperty); }
private set { SetValue(ActualOuterBrushPropertyKey, value); }
}
private static readonly DependencyPropertyKey ActualOuterBrushPropertyKey =
DependencyProperty.RegisterReadOnly("ActualOuterBrush", typeof(Brush), typeof(Clock), new UIPropertyMetadata());
public static readonly DependencyProperty ActualOuterBrushProperty = ActualOuterBrushPropertyKey.DependencyProperty;
}
and here is a little test program to prove that it works:
<Grid>
<Grid.Resources>
<Style x:Key="styleBrush" TargetType="local:Clock">
<Setter Property="Brush" Value="Red"/>
</Style>
<Style x:Key="styleInnerOnly" TargetType="local:Clock">
<Setter Property="InnerBrush" Value="Green"/>
</Style>
<Style x:Key="styleInnerOuter" TargetType="local:Clock">
<Setter Property="InnerBrush" Value="Blue"/>
<Setter Property="OuterBrush" Value="Yellow"/>
</Style>
<Style x:Key="styleEmpty" TargetType="local:Clock"/>
</Grid.Resources>
<StackPanel>
<local:Clock x:Name="clock" Orientation="Horizontal">
<Rectangle Width="100" Height="100" Fill="{Binding ActualInnerBrush, ElementName=clock}"/>
<Rectangle Width="100" Height="100" Fill="{Binding ActualOuterBrush, ElementName=clock}"/>
</local:Clock>
<StackPanel Orientation="Horizontal">
<Button Content="Default">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:ChangePropertyAction TargetObject="{Binding ElementName=clock}" PropertyName="Style" Value="{x:Null}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Content="BrushOnly">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:ChangePropertyAction TargetObject="{Binding ElementName=clock}" PropertyName="Style" Value="{StaticResource styleBrush}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Content="InnerOnly">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:ChangePropertyAction TargetObject="{Binding ElementName=clock}" PropertyName="Style" Value="{StaticResource styleInnerOnly}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Content="InnerOuter">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:ChangePropertyAction TargetObject="{Binding ElementName=clock}" PropertyName="Style" Value="{StaticResource styleInnerOuter}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Content="Empty">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:ChangePropertyAction TargetObject="{Binding ElementName=clock}" PropertyName="Style" Value="{StaticResource styleEmpty}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
</StackPanel>
</Grid>
This example uses behaviors. If you are not familiar with behaviors, install the Expression Blend 4 SDK and add these namespaces:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
and add System.Windows.Interactivity and Microsoft.Expression.Interactions to your project.

How to set focus on TextBox in Silverlight 4 out-of-browser popup

I have a simple ChildWindow popup in Silverlight 4 (beta).
Important: This is an out-of-browser application.
i want to auto set focus on a TextBox control when the window opens.
I've tried a couple things :
The following code doesn't seem to do anything. I don't think the control is ready to be focussed after 'Loading'.
private void ChildWindow_Loaded(object sender, RoutedEventArgs e)
{
textBox1.Focus();
}
This works, but its klunky.
private void ChildWindow_GotFocus(object sender, RoutedEventArgs e)
{
if (_firstTime == true) {
textBox1.Focus();
_firstTime = false;
}
}
Isn't there a better way? I always had to do horrible things like this in WinForms but was hoping not to have to anymore.
Note: This similar question is for in browser only. It suggests calling System.Windows.Browser.HtmlPage.Plugin.Focus(); which doesn't work and in fact gives an error when running on Silverlight 4 beta out-of-browser.
I was having the same problem in SilverLight 4 (OOB) and I noticed that the tab sequence would set focus to a control that i could not see. What appears to be happening is the focus is being set to your control (first one in the tab sequence) and then for some reason the focus moves to the ContentControl (name ="content"), which (i think) is the parent of the child window.
ContentControl by default has IsTabStop=true.
see....
Why would I want IsTabStop set to true on a ContentControl?
To set the ContentControl.IsTabStop = false for all ContentControls in your app, add this to your styles.xaml.
<Style TargetType="ContentControl" >
<Setter Property="IsTabStop" Value="false"/>
</Style>
The same issue happens with the tab sequence on the MainPage. This style will also fix this.
You are on the right track. You need to handle for two test cases:
1. Setting the focus in the browser.
2. Setting the focus out of the browser.
Your code you that you showed in the Loaded event will work perfectly fine out of the browser. All that is necessary is to refactor it to handle both cases:
private void ChildWindow_Loaded(object sender, RoutedEventArgs e)
{
if (App.current.IsRunningOutOfBrowser)
{
textBox1.Focus();
}
else
{
System.Windows.Browser.HtmlPage.Plugin.Focus();
textBox1.Focus();
}
}
That should do the trick for you.
Thanks for all the posts but after doing a little research the below thing work for me
in Xamal:
<TextBox VerticalAlignment="Center" HorizontalAlignment="Left" FontFamily="Arial" FontSize="12" Height="25" Width="200" Margin="38,50,0,0" Name="txtUserName" Text="{Binding LoginInfo.UserName,Mode=TwoWay, NotifyOnValidationError=True}" IsTabStop="True" TabIndex="1" ></TextBox>
// Initialiazing Main Part View Model
/// </summary>
/// <param name="mainPartViewModel"></param>
public ChildWindowLoginControl(MainPartViewModel mainPartViewModel)
{
InitializeComponent();
this.DataContext = mainPartViewModel;
System.Windows.Browser.HtmlPage.Plugin.Focus();
this.GotFocus += (s, e) => { txtUserName.Focus(); };
}
I had to use your GotFocus way for Silverlight 3 application written in IronPython when I wanted to set focus in ChildWindow.
I use:
protected override void OnOpened()
{
base.OnOpened();
textBox1.Focus();
}
Thanks for all the post, but i have find the work done through following.
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (App.Current.IsRunningOutOfBrowser)
{
txtSalesOrderNo.Focus();
}
else
{
System.Windows.Browser.HtmlPage.Plugin.Focus();
txtSalesOrderNo.Focus();
}
}

Resources