Dependency property in custom control bound to dependency property in parent user control is not updated before custom control DataContext is set - user-controls

I created a custom textbox to include validation. In this control is a dependency property called InputType. I capture the binding expression and add the rules when the datacontext is changed on the textbox.
public partial class ValidationTextBox : TextBox
{
public static readonly DependencyProperty InputTypeProperty = DependencyProperty.Register(
nameof(InputType),
typeof(TypeOfInput),
typeof(ValidationTextBox),
new UIPropertyMetadata(TypeOfInput.Text));
private void TextBoxDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
//...
SetBinding();
AddRules();
}
This works correctly when I use this custom control directly in an application. The dependency property is set then the data context is set. All is good as the rules are created after the property is set. However, if I add this custom control inside a user control and bind it's property to the user control's property of the same type in order to expose that property to the consumer of the user control, the rules are created before the custom control properties are set.
<UserControl ...
<local:ValidationTextBox
InputType="{Binding InputType, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
In this case, the dependency property of the user control is set, then the custom control data context is set, then the custom control dependency property is set. This means the rules are set using the dependency property default value rather than the actual value.
Is there a way to force the dependency property in the custom control to be updated prior to that control's datacontext being set or the control loaded?
I tried UpdateSourceTrigger=PropertyChanged but that doesn't work.
I have a bit of a hack that works. What I do is reset the rules when the InputType is set on the custom control by using a propertychangedcallback. This ensures the rules are set after the property is changed. The issue is that I have several more properties like InputType in the same control and again exposed to the user control and resetting the rules for each property seems like a bad idea. Any better solutions?

Related

Is there a way to prevent creation of a data class item in C# WindowsForms UserControl

If I create a UserControl, to create and edit an instance of a data class e.g. Person in C# WindowsForms (call it PersonControl), the framework automatically adds an instance of Person in PersonControl.Designer with some default values for the properties and fills the item controls with those values. This behavior has a number of side effects which I would like to avoid.
Question: is there a defined way to prevent creation of a data class instance in UserControl.Designer?
I think you missing the DesignerSerializationVisibility attribute. If you have a custom control every public property that you add will automatically be serialized. You can use this attribute to disable the serialization for a property. I also recommend to add the Browsable attribute which will hide the property from the designer. If you want more control over serialization, like you want to serialize only when another property is set to true you can create a special named method which will then called by the designer Defining Default Values with the ShouldSerialize and Reset Methods. There was a MSDN Magazine where a lots of winform learning resource was relased there are some gems about winform internal working. If you interested in you can quickly look trhrough it. My favorite is. Create And Host Custom Designers With The .NET Framework 2.0
Sorry but i didn't mention another attribute DefaultValue You can use the attribute the following way.
public partial class PersonEditControl : UserControl
{
[DefaultValue(null)] // This attribute tells the designer if the property value matches what we specified in the attribute(null) it should not store the property value.
public PersonData? Person { get; set; }
public PersonEditControl()
{
InitializeComponent();
}
}

Change custom entity properties programmatically with hook_entity_presave in Drupal 8

I created a custom entity with a string property qst_type. I would like to change this property programmatically before saving. I think you should use the hook_entity_presave or hook_ENTITY_TYPE_presave. Unfortunately I can not change this property with this hook.

UWP with Prism - handling more than one instance of UserControl on a Page

We're using Prism with UWP, and have a UserControl which we want to display several times in a Grid (each instance relating to a connected user).
If the UserControl were a Page, I know of course that the code can/should go in associated ViewModel. What's the equivalent for the UserControl? I obviously want to keep my code DRY, and call the same code for each UserControl instance.
My research is pointing me towards a Dependency Property, but I haven't found a clear example of how I should implement it.
Note that the UserControl needs to display data and also implement Buttons with associated Commands on the ViewModel.
Create a separate view model
You could create a view model specifically for the user control. The DataContext of the user control would be set to an instance of this view model. You can expose commands and data related to each user in the view model and bind to them in the user control, just like you would if it were a page.
This scenario works best if the user control can function independently of the page it is in. If you need the user control VM to communicate to the page VM, then you'll need to facilitate this somehow between the VMs (maybe the user control VM can take a reference to the page VM as a dependency upon construction).
Expose command properties in the user control
Another way is to create dependency properties for each command you want to expose in the user control, which can then be bound to in the page's XAML.
<UserControl>
<Grid>
<Button Content="Delete" Command="{x:Bind DeleteCommand}"/>
</Grid>
</UserControl>
public sealed partial class MyUserControl : UserControl
{
public ICommand DeleteCommand
{
get { return (ICommand)GetValue(DeleteCommandProperty); }
set { SetValue(DeleteCommandProperty, value); }
}
public static readonly DependencyProperty DeleteCommandProperty =
DependencyProperty.Register("DeleteCommand", typeof(ICommand), typeof(MyUserControl), new PropertyMetadata(null));
}
Now you can bind to DeleteCommand on the user control.
Typically I use some combination of both of these methods when I use user controls.

Setting Visibility based on another control's visualstate

Is it possible to set visibility on a Grid or other element based on the visual state of another control? I'm just starting to wrap my head around the VisualStateManager concept (having found that style triggers can't be used in universal apps) but can't work out if this can be done or not.
To my specific scenario, am I able to set the visibility of one or more elements if a specific item/index in a ListView is currently selected? If so, how?
I would maintain the ListView selection in a property of the viewmodel and bind Grid.Visibility to that property. You will need an IValueConverter to convert from the selected item's datatype to System.Windows.Visibility, which is required for Grid.Visibility binding.
In case the logic to determine visiblity is more complex, e.g. requires application state, you could add a property bool IsImportantItemSelected to the viewmodel and bind Grid.Visibility to this property. This approach allows you to keep the complex logic in the viewmodel. You'd need an IValueConverter again to convert from bool to System.Windows.Visibility.

Access a component of a custom control

I have a custom Control which I'll call ccViewTemplate with this code in it:
<xp:repeat id="repeatData" rows="30"
value="#{viewEntry}" var="veData"
first="#{javascript:return (sessionScope.ssFirst != null)?sessionScope.ssFirst:0;}">
<xp:panel id="panelSelect">
<xp:callback facetName="viewBodyFacet" id="callback1"></xp:callback>
</xp:panel><!-- panelSelect -->
</xp:repeat>
the database view (viewEntry) is also defined in ccViewTemplate and defined based on several custom properties. ccViewTemplate is then added to another custom Control called ccFinalView. Where the custom properties are entered, and the content of the display is entered into viewBodyFacet. I have access to veData and a everything works great to this point. In the viewBodyFacet I have a link that does a redirect to open the document which also works fine. However, in the link I want to get the repeatData Property First and store it so that it returns to the correct page of the repeat. I use this code:
sessionScope.put('ssFirst',getComponent("repeatData").first);
However, the code can not find the getComponent("repeatData") because it is inside ccViewTemplate and not accessible. Is there a way to get the component repeatData from the ccViewTemplate while in ccFinalView which contains ccViewTemplate.
I have done getComponent("ccViewTemplate") and I have the handle to the custom Control, but
getComponent("ccViewTemplate").getComponent("RepeatData").first fails. So is there a way to pull a value from a component 'inside' a custom control from 'outside' the custome control?
looked a little further and found this:
var rtn = getComponent("ccViewTemplate").getPropertyMap().getProperty("repeatData");
It does not generate an error but returns nothing, if I add
var rtn = getComponent("ccViewTemplate").getPropertyMap().getProperty("repeatData").first;
I get an error getComponent() is null
Hope this makes sense.
From what I understand, this is a perfect job for a java bean. The bean can even keep a default value.
public class Controller{
public String value;
public Controller(){
value = "default_value";
}
public String getValue(){return value;}
public void setValue(String value){this.value=value}
}
In this fashion, the value will be available as soon as the object is created. pressing the button then sets the value with javascript,
ControllerBean.setValue("thisValue");
and you can read the value
ControllerBean.getValue();
This question shows how to configure the bean: How to set up a managed bean to work with Notes document
By setting this to, say the viewScope, you can then access the value anywhere you need regardless of whether or not it is in a custom control or main page. I highly recommend this approach. It just means possibly rethinking your custom control structure.
EDIT
Extra ideas include having an enum that maintains the views,
public enum Views{
VIEW_1("viewAlias", "urlParam")
private String vwAlias;
private String urlParam;
private Views(String alias, String param){
vwAlias = alias;
urlParam = param;
}
// public getters
}
And then in your controller you can get the view string:
1. By seeing if a view param is included in the URL
2. If a cookie value is set
3. Take the hard coded default
Clicking the change view action then sets the cookie value and changes the view parameter and redirects.
This is all extra ideas, but it is how I build my view controllers. I will be doing a tutorial on that soon.

Resources