Access UserControl child controls? - xaml

I have a custom UserControl. That control has a Grid which I can access by name. But I can't seem to access the subcontrols from UserControl's constructor.
I can do:
this.LayoutRoot
but not
this.LayoutRoot.MyChildControl
how can I access this control programmatically?

If you used the x:Name attribute: x:Name="MyChildControl", you cen refference it in code behind regardless of nesting.
x:Name sets the FrameworkElement.Name property (but can be also used on objects other then FrameworkElement) and results in creating a field with this name which is assigned to in InitializeComponent().
So you can call simply:
this.LayoutRoot...
this.MyChildControl...
Note that FrameworkElement has a FindName method, which will work similarly to what you expected:
this.LoayoutRoot.FindName("MyChildControl")

By code you can create new object of your UserControl and then you can easily access user control elements by it's name.
MyUserControl ctrl=new MyUserControl();
ctrl.LayoutGrid.Background=new SolidColorBrush(Colors.Blue);
or generally
ctrl.ChildrenName

UserControl's child control can access by UserControl.Content. If you want to access your Grid's children, please use this.LayoutRoot.Children. You can enumerate this collection.

Related

What is DataContext in XAML?

Please describe what is DataContext in XAML and when use it and relationship between {Binding} syntax. (with example) (In simple terms)
Thank you a lot.
Data contexts are described within the Microsoft documentation here.
A datacontext is data accessible to (aka within scope of) the current element. Thus a TextBox might have a datacontext set to SomeObject. If you where to bind to this using a binding, like this:
<TextBox DataContext={binding Path=SomeObject} Text={Binding Path=MyString} />
the textbox would have a datacontext containing the values in SomeObject. Any binding performed on this element (or any nested elements) will be within this scope. So, the binding on the 'text' dependency property would try to find the value in SomeObject.MyString.
It's important to note that the data context is passed down to its child elements: if a datacontext is set on a parent and you do not explicitly override this on its child elements, then the children will also have the same data context.

Changing a oneway bound TextBlock value from code behind.

I have a TextBlock and its Text property is bound to a ViewModel property. The binding is Oneway.
When I change the Text property of the Control from the xaml.cs the binding gets broken. If the binding is TwoWay I don't have this problem but the source property is updated too. Is it possible to have OneWay binding and change the target property value without braking the binding?
I suggest a workaround, like setting the Binding to TwoWay and ignore the update in the property. Something like this:
private string textValue;
public string TextValue
{
get { return textValue; }
set
{
:
}
}
Now the Property can no longer be set by the view.
Although no code is provided, this scenario typically occurs when you have bound a control to a view model and at a later stage your logic tries to update the value in the control programmatically.
You should not try to do this, that is define multiple sources of the value for a control. If you bind the control to a property on the view model, then to update the value in the control you should update the field in the view model.
If you were to set the value of a bound control programmatically at runtime so that it no longer matched the bound object value, when some other event causes the control binding to be re-evaluated, the value that you have provided programmatically would be overwritten again, you could easily end up with a scenario where the value you provided programmatically is never visible to the user.
In this scenario you should either:
Add a new property to the view model, bind this value to the control, then your program logic can set this value equal to the original property when the data is loaded, and updated when you need to
Not use bindings at all, always write to the control programatically that way you tightly control when the value is updated.
There is a workaround to this if you absolutely must have one. if you are using compiled bindings (x:Bind), then because the bindings are compiled it is possible to call SetValue on the bound dependency property at runtime and the previously compiled bindings will still be evaluated. However I advise against exploiting this because it makes your code a lot harder to follow and debug, when bindings are used, we tend not to look for code that directly addresses and sets control values.

ExtJS: Binding an observable boolean property

I have a view which contains some tabs (TabView).
Initially some tabs are disabled - they should only be enabled when a certain condition is met.
I'd like to implement it in the following way:
Create a TabViewModel which contains a boolean (observable?) property PersonSelected.
Create a TabViewStore
Bind the TabViewStore to the TabView
In my controller I would have an action method (e.g. onPersonSelected) which will should set the PersonSelected property to true.
What is the best way to bind the PersonSelected property to the View?
As my store would only contain on record, I feel that using the is a bit overkill. Can I do this without the store?
You can simply subscribe to the change event of the UI element (checkbox? in your case). Am I missing something?

How to get Control from DataTemplate and ControlTemplate ? thinks so much

When i define a control in DataTemplate, how to get reference of this control ?
If the control in ControlTemplate of Style , how to get ?
You should instead tell us why you would need to reference a control inside a template.
Consider that the control will be rendered multiple times, so getting a single reference does simply not make any sense.
The most common approach to this is to 'name' the element that you wish to locate via x:Name="MyElementName", you can then use the FindName method to locate the names element. If your DataTemplate is being used in an ItemsControl to render multiple copies of yoru XAML markup, then clearly there will be a number of elements that share this same name. For this reason, there is a concept known as XAML namescope, you should read up on this to understand the scope of the name you provide.
If you require a more generic method for searching for elements in the visual tree, try Linq-to-VisualTree, you can use it to query you UI, for example:
var itemsFluent = this.Descendants<TextBox>()
.Where(i => i.Ancestors().FirstOrDefault() is Grid);
The above query will find all TextBoxs that have a Grid as a direct parent.
Finally, if you can avoid doing any of this, by using databinding, or event bubbling then do so! it is much easier.

How to correctly inherit from a usercontrol defined in XAML in Silverlight

If I have a usercontrol (in Silverlight) that I've written, that uses XAML to define it's appearance, how can I make a customised version of it?
i.e. I have MyControl.xaml & MyControl.xaml.cs
What do I need to do if I want a "SpecialisedControl" child class? I assume I just make a new code file, then inherit from MyControl. But what if I want to change the appearance of the base class - then what do I do?
I wrote this thinking you were talking about WPF, rather than Silverlight, but there may be enough overlap for this to be helpful, so I'm posting it, anyway.
If by "change the appearance of the base class" you mean "provide a new template", then what you need is probably a CustomControl, not a UserControl.
The best way to accomplish this is to follow the example set by other Microsoft controls, such as Button or ListBox:
Create a class that derives directly from Control (or whatever is closest to your control).
If any properties will need to be exposed to the control (such as text on a button, for example), make sure that you properly define them as DependencyProperties.
As described here, create a ResourceDictionary called Themes/generic.xaml and add a style for your class that includes a template (don't give the style a key).
Use TemplateBindings for any properties of elements on your control that need to get values from your control.
If you'll need to attach any event handlers to elements in your template, give them a unique name. Microsoft uses the convention of prefixing these names with "PART_", and I think it's a good thing to do for the sake of consistency, but it's not strictly required.
Again, if you need to attach event handlers, overload OnApplyTemplate(). In this method, you should detach any old event handlers (we certainly don't want any memory leaks!), and look for elements that have the names your provided in your template--when you find them, attach event handlers, as necessary.
This is certainly much more work than simply deriving from UserControl, but if you want to be able to totally re-template controls, like you can with the built-in controls, this is the way to do it.
On the other hand, if all you want to do is to provide a certain amount of limited customization, such as changing the background, or associating a Command with some user action, then the best thing to do is to expose DependencyProperties, which can then be set in styles for your control, or on instances of your control, itself.
In the case you mentioned of wanting to customize the look in an inherited control, the process is pretty similar: just add a default style for the new control with a new template; if you need to add more event handlers, just be absolutely certain that you call base.OnApplyTemplate().
I dunno, I like doing things with just plain objects. Here's an article that describes an easy way to slip a XAML-designed control outside your inheritance hierarchy so that you can customize appearance and behavior using SimpleThingsLikeInheritance rather than MicrosoftStuffThatAlmostWorks
http://gen5.info/q/2009/02/10/subverting-xaml-how-to-inherit-from-silverlight-user-controls/
As Mihnea's link describes, the easiest solution is to simply add a namespace in your XAML:
C#
public class MyBase : UserControl
{
}
public class FirstUserControl : MyBase
{
...
}
XAML
<local:MyBase
x:Class="FirstUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="YourAssembly" ...>
<!-- Sticking with UserControl instead of local:MyBase makes this clearer -->
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
..
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
..Your XAML
</local:MyBase>
You can solve this by using a wrapper as described in the link above.
But you can also use the strategy pattern to solve this problem.
In this post I explain how you implement these two methods.
http://www.lab101.be/2008/07/silverlight-usercontrol-inheritance/