I have two simple custom controls derived from standard WPF controls. I.e.
internal class CustomLabel : Label { ... }
internal class CustomButton : Button { ... }
(Ok, actually I use GridViewHeaderRowPresenter and DataGrid from WPF Toolkit, not Label and Button).
In xaml they locate on the same hierarchy level.
<Grid>
<CustomLabel />
<CustomButton />
</Grid>
The CustomButton control should react in some way to CustomLabel's event (say SizeChanged event). What is the best way to implement this?
So far I came to decision to traverse logical tree to find CustomButton in CustomLabel's event handler and change some properties. Is there better way?
Please note I am using .Net 3.5 so cannot use x:Reference markup extension.
You can give your controls names and access them using this name in your code behind. If you want to do it exclusively in XAML think about data binding and whether or not your goal can be achieved using this approach.
Related
How can I use the properties of the controls that are inside a user control without having to use DependencyProperty?
Since, if for example I want to use all the properties of a button, I would have to declare all these?
And if there is another way without user control and it is the correct one, I would appreciate it if you answered it. (Google translator, sorry)
UserControl:
<UserControl x:Class="UserControls.UserControl01"
...
>
<Grid>
<Button x:Name="uc_btn" />
<TextBox x:Name="uc_txt" />
<DataGrid x:Name="uc_dtg" />
</Grid>
</UserControl>
Code using the UserControl:
<Window x:Class="UserControls.wnd02"
...
>
<Grid>
<local:UserControl01 uc_btn.Background="Red" uc_txt.Margin="10" uc_dtg.BorderThickness="5" Margin="90" />
<local:UserControl01 uc_btn.Background="Green" uc_txt.Margin="25" uc_dtg.BorderThickness="20" Margin="5" />
</Grid>
</Window>
It is not usual to do what you are asking.
Let's consider a usercontrol which is intended to work as if it is one single control. For example a time picker. This contains two sliders which increase/decrease hour and minute. You can also overtype in the hour and minute textboxes and there's a : between the two textboxes.
This usercontrol is all about the one property though. Time. You don't care what the minutes background is externally. If this changes it's internal to the usercontrol.
In this scenario you'd usually add a TimeSpan dependency property to the usercontrol and this is the only thing anything external to it uses.
Pretty much all commercial WPF development uses the MVVM pattern and that TimeSpan would be bound to a property in the parent view's viewmodel.
That's one scenario.
Another is where a usercontrol encapsulates a bunch of UI which is then re-usable.
Styling has scope so when you apply a style to say a Button in a window then that would apply to any Buttons in a usercontrol within it. Setting their properties.
There are also certain dependency properties marked as "inherits" whose values propogate down the visual tree.
One such is DataContext and it is this which most teams would use to deal with properties within a usercontrol.
Using MVVM there would be a MainWindowViewModel.
That would have (say ) a ChildUserControlViewModel property. That would be associated with usercontrol using a datatemplate specified datatype.
You'd then bind properties of whatever is in a usercontrol to properties of ChildUserControlViewModel or properties of MainWindowViewModel using RelativeSource binding.
ViewModel first is a common navigation and composition pattern for WPF. You should be able to find numerous blogs explain it better than I can in a SO post.
Here's one:
https://social.technet.microsoft.com/wiki/contents/articles/30898.simple-navigation-technique-in-wpf-using-mvvm.aspx
I have situation like this, I have 2 WPF forms developed using MVVM Pattern ..2nd form will be opened from first(form1 will be in backend till form2 is closed) and closing the second makes the first form active.
Now I want to make a textbox on form1 with default focus set on it. I was able to do it with FocusManager and its working fine but the same is not working fine when Im getting into form1 from form2. Also during this time I have to set the focus on the default textbox and also I need to select all the text present on it. I am unable to understand how to do this with viewmodel.
Any suggestions will be of great help for me.
Regards,
Krishna
You can focus a particular UI element using the FocusManager.FocusedElement Attached Property:
<Grid FocusManager.FocusedElement="{Binding ElementName=SomeTextBox}">
<TextBox Name="SomeTextBox" Text="{Binding SomeProperty}" />
</Grid>
This should select the TextBox each time the view/UserControl is loaded.
As for how to select text from the view model... the solution would be the same to handle any event when using MVVM. Wrap it in an Attached Property. Please beware that it is not appropriate to handle all events in the view model, as it should not really have any knowledge of purely UI events. However, the choice is yours.
To 'wrap', or handle any event in an Attached Property, you basically declare a class that extends the DependencyObject class and define one or more static properties. Rather than go over the whole story once again, I'd prefer to direct you to my answer to the What's the best way to pass event to ViewModel? question on Stack Overflow, which provides further links and a full code example.
For background information on Attached Properties, please see the Attached Properties Overview page on MSDN.
What are the benefits and downsides of implementing a custom control in XAML by inheriting from UserControl:
<UserControl x:Class="MyButton" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Button>
<!-- custom content here -->
<!-- custom behaviors in the code behind -->
</Button>
</UserControl>
vs inheriting from the control I'm putting inside the UserControl?
<Button x:Class="MyButton" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- custom content here -->
<!-- custom behaviors in the code behind -->
</Button>
There is no benefit to using a UserControl if you really want a Button. A UserControl just provides a simple way to create a control. From the UserControl Class page on MSDN:
If you do need to create a new control, the simplest way is to create a class that derives from UserControl. Before you do so, consider that your control will not support templates and therefore will not support complex customization. However, deriving from UserControl is a suitable model if you want to build your control by adding existing elements to it, similar to how you build an application, and if you do not need to support complex customization. (If you want to use templates with your control, derive from Control instead.)
As the remarks from MSDN note, using UserControl instead of Button as your base class will mean that your control cannot be templated, whereas when using a Button as the base class, you could still provide a new ControlTemplate.
You should always use the control that most closely suits your needs as the base class. The UserControl is only there to provide an easy way for us to add a collection of already existing controls to the UI. If that is not what you want to do, then don't use it.
I am trying to switch off the grid visibility of a RadDiagram I have.
I am creating a User Control using Telerik controls within a Silverlight Project (sharing the control with a WPF Library).
It seems that RadDiagram Property is not found. (RadDiagram Commands - Found property here)
PS: I am creating and filling the shape programmatically. Therefore, I need to an approach to switch the grid off that apply to Style attribute in Resource Dictionary or a simple programmatic property set / function call.
Thanks,
The way to turn off the BackGroundGrid or BackGroundPageGrid is to use these attached properties:
<telerik:RadDiagram x:Name="diagram" Margin="30"
primitives:BackgroundGrid.IsGridVisible="False"
primitives:BackgroundPageGrid.IsGridVisible="False"
where primitives is defined like so:
xmlns:primitives="clr-namespace:Telerik.Windows.Controls.Diagrams.Primitives; assembly=Telerik.Windows.Controls.Diagrams"
If you need to bind the command for switching the BackGroundGrid On / Off , you can use this syntax:
<telerik:RadButton Command="telerik:DiagramCommands.SwitchGridVisibility"
CommandTarget="{Binding ElementName=diagram}"/>
Programmatically in code-behind here is how it is done:
Telerik.Windows.Controls.Diagrams.Primitives.BackgroundGrid.SetIsGridVisible(this.myDiagram, false);
Source: Switch Grid Visibility
I'm using the 'Extended WPF Toolkit' ( http://wpftoolkit.codeplex.com/ ),
and for my own purposes I've created a generic version of its NumericUpDown control called GNumericUpDown< T > which actually lets me specify what type to use, ie. GNumericUpDown< int >.
(This is done to make sure the control respects the appropriate Min/MaxValues of the wanted type)
To be able to use different types from Xaml, I've created a new project with specific derived versions, f.e. NumericUpDownFloat which is derived from GNumericUpDown< float>.
But when I use the NumericUpDownFloat in XAML, nothing is displayed.
I assume this is because there's only a style specified for the WPF Toolkit's NumericUpDown in the Generic.xaml resourcedictionary of the WPF Toolkit project.
So how can I make all my specific versions (NumericUpDownInt, NumericUpDownByte, ..) actually use that style ?
You should get the latest source code for the Extended WPF Toolkit. The updated NumericUpDown control allows you to specify what data type to use in the editor. The following code specifies to use an Int32 as the data type instead of the default double. As you can see this is done by setting the ValueType property on the NumericUpDown control.
<extToolkit:NumericUpDown Grid.Row="1" Value="{Binding Age}" Increment="1" Minimum="18" Maximum="65" ValueType="{x:Type sys:Int32}" />
This will eliminate the need for the seperate project with specific dervied controls.
By default when you make any type of custom control, WPF puts this in the static contructor of the class for you:
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
This tells WPF that you are going to supply a theme for it somehow. By default, a Themes folder will be created at the root of the project, with a Generic.xaml file created with the CustomControl1 style and control template put inside of it.
If you want to tell WPF you will be override the style (or really, overriding the default style key dependency property), you just put that line in you static constructor. If you want it to fall back to whatever it's parent style is, you just omit that line and something like this:
public class SuperAwesomeControl : Border
{
....
}
Will always look like border by default.