So I've gotten in the habit of using WPF/C# value converters because they are awesome. I usually just have a folder set up for value converters and then access them in whatever xaml files I might need them.
I'm currently developing a user control that will have some value converters that I do not want other classes to be able to access. In other words, value converter exists in the code behind file and should be accessible only from that file and the associated xaml. My first thought was to throw it inside the code behind file as a nested class, but I can't find a way to access the nested class from within the xaml file. Am I going in the right direction or is there something else I should be doing?
I could go the cheap way and just throw this control into its own namespace, but that doesn't really solve my problem.
Any help or guidance is appreciated. Thanks!
Below is roughly what I want:
public partial class MyControl: UserControl
{
//misc code for control
private class MyValueConverter : IMultiValueConverter
{
//conversion functions
}
}
is what I have in mind.
Normally, value converters are accessed from WPF like:
`<local:MyValueConverter x:Key="MyValueConverter" />`
This only works if they are in the same namespace. I cannot get this to work if it is a nested class. I've met my goal of making the valueconverter visible only to this user control, but I cannot figure out for the life of me how to access it from within the xaml.
My problem is accessing this converter from in the xaml.
It is not possible (look here for the reason - 2nd paragraph about requirements)
Your custom class must not be a nested class. Nested classes and the "dot" in their general CLR usage syntax interfere with other WPF and/or XAML features such as attached properties.
You can of course work around that - but that limits you to setting the valueconverter in the code-behind (which is yucky :-))
I'm curious, though, why would you not want other classes to use it?
In your code-behind file, mark the methods that contain your converter code as private just like you would any other methods or properties that you wouldn't want to be visible outside of the class. Remember, the XAML and the code-behind file are (by default) both partial representations of the same class, so anything you declare in your code-behind file, even if private, is still visible to the corresponding XAML file.
Related
I have a UserControl with a custom property:
public Size TestSize { get; set; }
I would like this property to show up in the properties window during design time of the UserControl, and not only where the UserControl is used as an instance (e.g. when dragged/dropped on a form).
Example:
In the designer of the UserControl one can set properties like "AllowDrop", "AutoScroll", "BackColor" etc. I would like my custom property to show up just the same way in the designer.
I have considered and tried adding attributes to the property like:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
but that does not seem to be the way to go.
Any help is appreciated!
If you really want to show the property in the designer of UserControl1, then the property should belong to its base class. That's because of how designer works
Assuming the root element of the designer is UserControl1, then the properties that you see in properties window, are browsable properties of UserControl1's base class (which is probably a UserControl). To learn more about it, read the second section of the answer.
In most cases you don't need to show those properties in designer, unless you want to derive multiple controls from that base and configure that property in design-time of the derived control, but I assume you know your requirement and now you are able to make a decision base on your requiremets.
This is the way that designer works:
It deserialize the .cs file (and looks for InitializeComponent method, or designer.cs file, also considers the designer-related attributes).
It creates an instance of the base class and add it to the design surface, and applies the deserialized property values. (So the instance that you see in designer, is an instance of the base class. It's a trick. For example, that's why if you have an abstract base class, you cannot have the derived class as root designer without some workarounds.)
It creates the whole control/component trees based on the deserialized code. (So the controls which are on design surface are real instances of the controls)
Of course there are a lot of other things happening, like making the extender providers working, or pre-filtering or post-filtering properties in design-time, but in general it works like what I explained above.
More information / Related Posts
Some other related answers:
A similar question/answer for Form: Custom browsable property for Form at design time
An answer explaining how designer works, also contains an interesting example shows how .cs file which is full of syntax errors can be shown in designer: How does Windows Forms Designer work?
Let's say that I want create a specialized wpf control, "YellowTextBox". It will be the same of a common TextBox, but it will be... yellow!. Ok, I go to code:
public class YellowTextBox: TextBox
{
}
Now, the obvious part, I want it be yellow...
this.Background = Brushes.Yellow;
Where I put that line of code? In the constructor? In OnInitialized override? OnLoaded, etc...
There are some correct (or better) place to put that line of code?
EDIT:
I know I can do it via styles, my question is more an "OOP" way of do it, it can be any other kind of property or field, not exactly Background Color, that selected property was just an example :/
You really ought to initialize a specialized WPF control in the initializers for the dependency properties (for properties it introduces), and in the default Style (for the new properties, and for anything it inherits that needs a different default value).
But you want to do it in C#, for some reason.
In that case, we're talking about a) OOP theology, b) OOP reality, and C) WPF mechanics. In terms of all of those, do it in the constructor, and in WPF, in the constructor after InitializeComponent() (if applicable, not in your case) is called. That'll precede any styles that get applied to the control in WPF, and it's good OOP practice and theology to initialize everything in the constructor that you didn't initialize in field initializers. A new instance of a class should be ready to go, in a consistent state that won't throw any exceptions if you start using it. So that means the initialization should be all complete at that point. Never leave any initialization to anybody else. That's a booby trap.
Do read up on InitializeComponent(), but in your specific case, the constructor for a subclass of a standard control, you won't be calling it.
A control subclass in WPF will apply styles after the constructor. It must! Before the constructor executes, it doesn't exist. "After the constructor" is basically all there is, aside from the guts of the constructor itself. You can override OnApplyTemplate() to hook into things immediately after the template is applied. But that's much too late to be initializing much (with the exception of private fields which will refer to template children).
So if you initialize stuff in the constructor(s), it gets applied to every instance, and if it's a WPF control class (or any FrameworkElement subclass), consumers of your class can override it by applying a Style or a template later on. That's good WPF practice: You want to allow people maximum scope to customize your controls.
I have a .NET PropertyGrid control which displays properties of some class. I want to change the color or font or background color(it doesn't matter just that they look different from the other displayed properties) of some property. I can do with writing custom editor but I was wondering:
If an easier method exists?
If I use custom editor then how do i change the editor of built-in types like bool, int etc?
No can do. The class that determines how an item is drawn is PropertyGridView. The source code is interesting, it almost made it:
private /*protected virtual*/ PropertyGridView CreateGridView(IServiceProvider sp) {
return new PropertyGridView(sp, this);
}
Nope, looks like at the last minute they decided against making the method overridable. The PropertyGridView class was also marked internal. Replacing all this code (there is a lot of it) is not a realistic option.
Creating your own UITypeEditor for built-in types is only possible by applying the [Editor] attribute to the properties in the class you want to edit. That's not a general solution. Consider creating your own form to make the object editable instead.
I'm trying to databind (ideally from XAML as i know how to do this in code behind but it would be far from trivial to traverse my heavily templated tree just for that) to a property who's name i only know at runtime
What i would like to do is not the usual:
Content="{Binding TheProperty}"
But something like
Content="{Binding PropertyName=TheNameIsStoredInThisProperty}"
I'm trying to do this because i generate the UI from templates when binding to my plugins, but the UI is specified in a set of POCO and separate from the ViewModel, so i want to be able to generate my UI and still be able to wire it to the correct properties on the ViewModel, any advice is most welcome.
The immediate solution might be to bind to an arbitrary property in your VM with an IValueConverter that goes both ways, and the ConverterParameter is the string containing the source property name. Once inside the value converter you can use an interception pattern to Reflect out the value you need from the POCO. You can then pass the value up to the source property in the VM. Rather like a pipeline :) This will work but still leaves you with being notified when the POCO changes.
A Markup Extension seems plausible but likely to be brittle and provide naught in the way of performance improvement.
An Attached Behaviour still leaves you with having to Reflect and does not easily solve the problem of notifications originating in the POCO (AFAIK only Unity knows how to do that).
So what I am trying to do is to have a set UI with certain controls, and I want to have some class instance to fill in the values.
For instance:
Classes that can populate the UI:
Sharpen, Blur, Smear, ... : FilterBase
So whenever the user creates an instances of the above classes, I want to automatically fetch the values based on the UI controls, by using the class instance.
The UI has items like:
.Name (TextBox)
.Amount (NumericUpDown)
.Decay (NumericUpDown)
So if the current instance is s = new Sharpen(), I want to get s.Name to fill out UI.Name.
How do I do this in the best possible way? Elegancy, clarity, performance wise, etc.
I am gonna use reflection, but how do I store the instance of the object (Sharpen, ...) and be type safe? Should I use an System.Object instead? Or T?
public partial class ParamsUI
{
T CurrentFilter (?)
...
}
Also if I use T, how will I know what to cast it to?
Is there a better way?
Since this is using Windows Forms, the most flexible option would probably be to just use the Windows Forms PropertyGrid directly.
You can do a lot of work to customize the look and feel of this. See Getting the Most Out of the .NET Framework PropertyGrid Control for details.
Edit:
If you want to have a very flexible, easy option, and WPF is an option (hosted within an ElementHost), you could consider using WPF.
With this, you could host a UserControl containing nothing but a resource dictionary and a ContentControl.
You could then make a custom XAML file for each item you want to edit, and setup a data template in the resources specifying the mapping of which user control (xaml) to use for each element you want to edit. You can then just set the element to the user control's "DataContext" in code, and it will automatically wire everything up and "just work".