I have defined a textbox with x:Name="txtMyTextBox" inside UserControl called MyView. I've noticed that I can do the following:
MyView myView = new MyView();
myView.txtMyTextBox.Text = "something";
Why txtMyTextBox is accessible that way? Is it public or internal field? Can I make it private?
The Silverlight XAML designer creates fields for named elements so that you can access them from the code behind. You can see the generated file if you go into the code behind and choose InitializeComponent from the method selection drop down at the top. It's kept in a partial file. In the past, designer generated fields have been scoped as private, but for some reason I cannot fathom, the current crop of XAML designers (VS2010, Blend) creates it as internal.
You can change the visibility of the field that gets generated by using the x:FieldModifier attribute but you probably don't need to worry about it. If you need to, you should expose a public property from your user control that wraps access to it instead.
Related
I'd like to create a WPF user control (or custom control). The user of this control should be able to re-template a certain part of this control. For that I created a dependency property called "SubTemplate".
Public Shared ReadOnly SubTemplateProperty As DependencyProperty =
DependencyProperty.Register("SubTemplate", GetType(DataTemplate), GetType(MyControl), New FrameworkPropertyMetadata(Nothing))
Of course there should be a default template that's used, when the user doesn't give it's own template. But how do I give this default value to the dependency property?
I'd like to define this default template in XAML (probably in a resource dictionary, maybe in Themes\Generic.xaml?)
Is there a way to exchange the Nothing default value with a template from a resource dictionary?
Or do I have to set the default value in the constructor of my control (still don't know how to access a named template from a resource dictionary in code behind, FindResource doesn't seem to work or I'm using it wrong).
Or do I have to set the TargetNullValue of the binding I use to add the template to the re-templated part of the control?
Right now I just set the "SubTemplate" property in the default style of my control, but if the user restyles the whole control and forgets to give a "SubTemplate", then it would be Nothing.
Is there a way to exchange the Nothing default value with a template from a resource dictionary?
If you add the default DataTemplate to your App.xaml file, this should work:
Public Shared ReadOnly SubTemplateProperty As DependencyProperty =
DependencyProperty.Register("SubTemplate", GetType(DataTemplate), GetType(MyControl), New FrameworkPropertyMetadata(Application.Current.Resources("KeyOfTemplate")))
If you want more control over things you could write some code that looks up the template, for example in the OnApplyTemplate method of the control. You may want to get it from somewhere else, check that it actually exists, etc.
Windows Phone 8 project, XAML. I have a ListBox inside a pivot item that's of my own class MyPivotItem (derived from vanilla PivotItem) inside a page. The listbox has an ItemTemplate with some controls. I'd like to bind an event in one of those controls to a method in MyPivotItem. The plain syntax Click="OnClick" does not work - the frameword searches for the method in the Page class only.
I could derive the control itself and do some trickery with tree navigation and event forwarding and so on, but I wonder if such a scenario can be served by XAML's internal means.
Is there any way to bind methods non-programmatically to a class that's deeper in the hierarchy than the root object of the XAML file?
Without using something like behaviors or attached properties, it is not possible. XAML file is always associated with partial C# class and in this class you define your controls and events. For every Page.xaml, a Page.g.xaml file is generated that actually creates controls and binds events. However, those events must be defined in root object - the partial class itself.
Even if you create a workaround using either attached properties or behaviors, you are simply offloading that programmatic code to some other place and hiding it behind XAML syntax.
When would you want to bind to control's specific event handlers anyway? Can you simply use UserControls for that?
I have read multiple posts on the subject but still cannot manage to make it work.
I want 2 user controls slidertype1 and slidertype2 which should inherit from slidercommontype, all are in same namespacecommon, can someone knows the syntax for this simple use case ?
Inspiring from http://jamescrisp.org/2008/05/26/wpf-control-inheritance-with-generics/
I tried:
<namespacecommon:slidercommontype x:Class="namespacecommon.slidertype1">
but I got namespacecommon:slidercommontyp doesn't exist in xml namespace.
As long as the base class doesn't have a XAML file associated with it, it's pretty easy. Trying to incorporate the visual aspect of the user control using XAML is not really a supported scenario.
Having said that, just create your class SliderCommonType (although I would call it SliderBase or something.)
namespace MyControls {
public class SliderBase : UserControl {
}
}
Then create your two controls based on it. I'll show one example and the other should be obvious.
<Local:SliderBase x:Class="MyControls.SliderType1"
xmlns:Local="clr-namespace:MyControls">
</Local:SliderBase>
And the code-behind would look like this:
namespace MyControls {
public class SliderType1 : SliderBase {
}
}
The key point being that your XAML file has to reference the base class which requires changing the <UserControl> element to <Local:SliderBase> which in turn requires a XAML namespace import.
When you add a UserControl using the default template, you can just change the code it creates to reflect the above changes. It's much easier than trying to create it from scratch.
One last thing to note - you will need your application to compile successfully before you can use the visual designer on your derived controls. This is because the designer needs to be able to instantiate SliderBase at design-time.
I would like to create a Silverlight custom control using C# only, without any xaml.
Here is my work so far (stripped down to the bare minimum for the question):
I tried to inherit User control as follows:
public class myControl: UserControl
{
// class code
}
And adding it to the LayoutRoot:
myControl control = new myControl();
LayoutRoot.Children.Add(control);
The control is added, but its invisible!!
How can i make it visible ? Is there something i missed ?
edit: The only visual element in my contorl is a grid with an image background
Your Usercontrol will be empty and have no visual effect until you give it a child control via it's Content property.
Well unless you put a template in place or add elements in code, UserControl is empty.
Maybe you could try inheriting from an existing control which has a template, like Button, etc and change that in code?
I've run into a puzzling limitation in a Silverlight 4 UserControl.
What I'm trying to achieve is to have a panel, which slides out from a minimised state when a button is pressed, but the title bar of it should be draggable with which this maximised state can be resized.
What I've done for the sliding out is to animate the MaxHeight property of the parent Grid of this panel which works quite well even with no hardcoded Height for the panel, but I don't know how can I make this dynamic.
Trying to bind a variable from the code-behind to the 'To' parameter of the 'DoubleAnimation' didn't work, it just silently gets ignored.
As I'm creating UserControls to represent Views, the elements with x:Name properties won't get autogenerated.
I tried to work around this using the code below which mimics what happens in the autogenerated code (with the added bonus of only being done after the layout is actually loaded):
public DoubleAnimation PanelOpenMaxHeightDoubleAnimation;
private void LayoutRoot_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
var LayoutRootreference = sender as Grid;
PanelOpenMaxHeightDoubleAnimation = ((DoubleAnimation)(LayoutRootreference.FindName("PanelOpenMaxHeightDoubleAnimation")));
PanelOpenMaxHeightDoubleAnimation.To = 383;
}
This however breaks when trying to set the value of To, as FindName returns null (I have x:Name manually set in XAML for this particular animation to "PanelOpenMaxHeightDoubleAnimation"). I have the sneaking suspicion FindName can't pick DoubleAnimations up from VisualStates, only actual layout children?
I did find the documentation about XAML Namescopes at http://msdn.microsoft.com/en-us/library/cc189026(v=VS.95).aspx#UserControls, but didn't really understand what my options are from this paragraph (other than being very limited):
For the case of a UserControl, there is no equivalent template part attribute convention for parts of the UserControl in the definition XAML, nor is there a template applied at all. Nevertheless, the namescopes between definition and usage remain disconnected, because the definition namescope is defined and then effectively sealed when you package your UserControl into an assembly for reuse. A best practice here is to define your UserControl such that any value that needs to be set to modify the definition XAML is also exposed as a public property of the UserControl.
What does it mean by the last sentence?
Wondering can I do next? Should I try to generate the entire state from code?
Well, managed to work it out so I'm sharing the solution.
Instead of trying to get a reference to the DoubleAnimation in Resources, I named the Grid in the layout I want to animate and get a reference to that using the code in the original question:
var SlidePanel = ((Grid)(LayoutRootreference.FindName("SlidePanel")));
This does return the element and using that it's possible to create a DoubleAnimation and a Storyboard from scratch purely in code. I just used this code example as a starting point: http://msdn.microsoft.com/en-us/library/cc189069(VS.95).aspx#procedural_code
Best part is, you can change the DoubleAnimation.To parameter even after setting everything up in the Storyboard, so now what I'm doing is just resetting that to my calculated value every time before calling Storyboard.Begin().
It's a bit fiddly to set all these up manually, but at least it works nicely once you do.