We use controls all the time for example a button and sometimes we may want to add some custom properties to that button. For example numberOfTimesClicked etc. I am currently working with GridViewColumnHeader and I would like to add the property columnIndex to that class. I know I can keep track of the columns with other methods but I am just curios to know if we can add extra properties to classes. For example I was thinking about inheritance. If I create a new class and inherit from the class that I want to add new properties (in my case GridViewColumnHeader) then I think that should work but for some reason I get errors in my code whenever I do something like:
private class MyGridViewColumnHeader : GridViewColumnHeader
{
public int propertyThatIWantToAdd { get; set; }
}
from now on if I instantiate objects from MyGridViewColumnHeader class instead of GridViewColumnHeader class I get errors. What is wrong with using inheritance to achieve this?
Instead of casting the sender object use
e.OriginalSource as MyGridViewColumnHeader
And do your work on that object. If you need to know what is inside the RoutedEventArgs have a look on MSDN
You should make the class public, the private modifier is only allowed for inner classes.
Also you should use Dependency Properties instead of normal Properties, if you want to access the property in XAML.
Related
I am currently building an application that contains a structure similar to this:
public class ViewModel
{
public string property1 {get;set;}
public string property2 {get;set;}
public ISomeInterface interfaceProperty {get;set;}
}
Which then has several different classes defined that implement ISomeInterface.
Is there a way to represent the interfaceProperty as a combobox of choices that would let me change the type that is stored there, without resorting to wiring that all up in the code behind?
Extra wrinkle, I would also like to show some databound textboxes to configure various properties in the selected type, which would change when the type is changed, is this possible?
Is there a way to represent the interfaceProperty as a combobox of choices that would let me change the type that is stored there, without resorting to wiring that all up in the code behind?
Maybe, depending on what you actually want to do. If you simply want to bind a collection of existing objects to the ComboBox as the selection options, that should work fine. But obviously in that case, if you are using this UI with more than one instance of your ViewModel type, each instance would wind up with the same ISomeInterface object for a given implementation type. This may or may not be acceptable.
If you want to automatically detect all available implementations of ISomeInterface and populate the ComboBox with the types themselves, creating a new instance for the ViewModel each time the selected implementation changes, then no…that's going to require some code-behind.
If you do want unique object instances, but are okay with manually specifying the options, then you could do it with e.g. a collection of factory delegates, or implementation of IValueConverter (e.g. to convert a string or Type value from the ComboBox to a new instance of the desired type).
Unfortunately, your question is light on requirements, so it's hard to know what would work for you. There are lots of options, and enumerating them all would be "too broad" for Stack Overflow.
I would also like to show some databound textboxes to configure various properties in the selected type, which would change when the type is changed, is this possible?
Sure. Just declare appropriate DataTemplate resources for the different types you want to handle, and use ContentPresenter with the Content bound to the instance of the type you want to display.
So I have a class; lets use the ScrollViewer class as an example. It has a dependency property called Content which accepts anything of type System.Object, great!
Let's say I derive a class from ScrollViewer, lets call it ZoomScrollViewer, it adds some basic zooming and panning using the mouse with a keyboard press. It also adds a dependency property of it's own, AutoscaleContent.
Now, I want to be able to put a ZoomScrollViewer into a UI window, but I only want it to accept a Canvas as it's content. Naturally, I go about creating a ZoomScrollViewer<T> class.
However, how can I change the Content property so that only accepts elements of type <T>? Can I override the dependency property? I got a little confused and tried:
public new T Content
{
get { return (T)base.Content; }
set { base.Content = value; }
}
But of course this makes it no longer a dependency property, so all the XAML code fails when I set up the bindings.
Edit: It should also be noted that I've taken a look at using:
ZoomScrollViewer.ContentProperty.OverrideMetadata(typeof(ZoomScrollControl2<T>), new PropertyMetadata(...?));
To see if I could do anything using that, but it seems you can only override the default value, unless I'm missing something?
Update: I've now tried using the following:
public class ZoomScrollControl2<T> : ZoomScrollViewer where T : FrameworkElement
{
static ZoomScrollControl2()
{
ContentProperty.OverrideMetadata(typeof(ZoomScrollControl2<T>), new FrameworkPropertyMetadata(typeof(ZoomScrollControl2<T>)));
}
}
public class CanvasZoomControl : ZoomScrollControl2<Canvas>
{
}
Which I thought would work, but it still seems to accept a Content of any type.
Update: In short I'm not sure if what I want to do is even possible, so I've marked the discussion as the answer, even though it isn't an answer per-se.
I suggest to try that approach as it suggested by this MSDN article.
It should override the referal type, so you can refer to it using derived type.
Dependency Property visibility is not made esplicit in .NET Framework for derived types, as searching right property among the types tree has a cost in terms of performance, and considering that we use DP on UI binding, it can lead to non desirable performance issues.
I have a class I am working with:
public sealed class WorkItemType
It's ToString is weak (Just shows Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemType).
Is there any way to override this to show the name of the WorkItemType?
Normally I would just aggregate the value in a new class, but I am using this for bindings in WPF (I want to have a list of WorkItemTypes in a combo box and assign the selected value to a bound WorkItemType variable.)
I think I am out of luck here, but I thought I would ask.
A fairly neat way to do it might be to add an extenesion method to the WorkItemType object. Something like this:
public static class ToStringExtension
{
public static string MyToString(this WorkItemType w)
{
return "Some Stuff"
}
}
Then you could call something like
WorkItemType w = new WorkItemType;
Debug.WriteLine(w.MyToString();)
Do you need to override ToString? If you are in control of the code where the object is displayed, you can always provide a FormatWorkItemType method, or something to that effect.
WPF provides a few different built-in ways to do this right in the UI. Two I'd recommend:
You can use ComboBox's
DisplayMemberPath to display a single
property value but still select from
the WorkItemType objects.
If you want to display a composite of
a few properties you can change the
ComboBox's ItemTemplate to make it
look pretty much however you want -
formatting text, adding borders,
colors, etc. You can even set up the
DataTemplate to automatically be
applied to any WorkItemType object
that gets bound anywhere in your UI
(same basic effect from UI
perspective as changing ToString) by
putting it into Resources and giving
it only a DataType with no x:Key.
You're out of luck :-(
You could write your own class that wraps the WorkItemType and delegate down to it (a proxy) expect for the ToString:
class MyWorkItemType
{
private WorItemType _outer;
public MyWorkItemType(WorkItemType outer)
{
_outer=outer;
}
public void DoAction()
{
_outer.DoAction();
}
// etc
public override string ToString()
{
return "my value"
}
}
I don't have any C# knowledge, but can't you wrap your extended class inside another class? Proxy all method calls to the extended class, except toString(), Also very hackish, but I thought I'ld bring it up anyway.
Doing some sorta magic with reflection is probably your only hope. I know you can instantiate private constructors with it, so maybe you can override a sealed class... Note, this should be your last resort if there is seriously no other way. Using reflection is a very hackish/improper way of doing it.
In addition to the other WPF-specific answer you could use an IValueConverter in the binding to format / display the WorkItemType however you want. This has an advantage of being reusable (if you want to display the object in some other control, for instance.)
There are many examples of using converters here. This other question should be pretty similar to the ComboBox usage mentioned here. The answers note that you can either make the converter work on the entire collection of objects, or work on one item at a time. The latter might be the more reusable approach.
I have a class that implements properties in a specific way, to handle some custom requirements for our business logic system.
This "specific way" makes the properties non-operational in the context of data binding. Basically, if I drop an object of our class onto a form, data binding finds nothing on the object, and the property inspector for that object, though it lists the properties, doesn't allow me to edit them.
What I'm wondering is if there's an interface or similar that I can implement in my class that will report to the form designer what properties could be bound to, and that implements the custom code necessary to talk to the data binding system on behalf of my properties.
Note that I do not need to be able to edit the property values for my object in the property inspector, that was just an example of how non-functional the properties are. I just need the data binding support.
Is there such an interface, and if so, what is it?
Let's give a simple example.
Let's assume I have this class:
public class CustomDataBinding : Component
{
private Dictionary<String, Object> _Properties = new Dictionary<String, Object>();
public CustomDataBinding()
{
_Properties["Property1"] = 10;
_Properties["Property2"] = "Test";
}
}
Is there anything I could do to my object, short of actually making the properties, that would add data binding support for those two "properties"?
Note that for my real class, I know the type of every property, so if it makes it easier, change the above code to just use string values:
public class CustomDataBinding : Component
{
private Dictionary<String, String> _Properties = new Dictionary<String, String>();
public CustomDataBinding()
{
_Properties["Property1"] = "Property1";
_Properties["Property2"] = "Property2";
}
}
I will also need validation support, as our class can report validation status for every property as well, but I have already implemented IDataErrorInfo and IDataValidationInfo which I think will give me that. I have also implemented INotifyPropertyChanged, so I got the change mechanism in place I think, but I need to discover and talk to the properties. Beyond those interfaces, anything else I should look into would be welcome information.
It sounds like you are describing a property-bag; this is indeed supported for data-binding, but you need to implement ICustomTypeDescriptor or TypeDescriptionProvider. The available properties are then defined via TypeDescriptor.GetProperties(obj) or TypeDescriptor.GetProperties(type) - or in the case of lists, via ITypedList. ICustomTypeDescriptor is suitable if the properties change per-instance; TypeDescriptionProvider can do per-type customisation, and works with things like BindingList<T> without any extra work.
The tricky thing is that you need to define the type of each property - not simple if you've just got object. Here is a very simplified example, that treats all properties as strings. In this example, because we are binding a list, it uses ITypedList but doesn't implement ICustomTypeDescriptor.
Note that for PropertyGrid, a simpler shortcut is to use a TypeConverter - this allows you to tweak the properties without having to use ICustomTypeDescriptor or TypeDescriptionProvider - see example.
You could always expose the Dictionary as a property and access elements of it directly (though it'd need to be by index and implement IListSource or IEnumerable.
-- Edit
I must say, though, you're effectively making your own untyped language. Interested in the reason for this, perhaps there is a better way ...
Since you can't publish new properties, how about publishing your Dictionary as an ObservableDictionary<string, object>. See this DrWPF article.
You could then bind to the dictionary using the key to get the named property you're after.
So we have a C# WinForms project with a Form that contains a bazillion UserControls. Each UserControl naturally exposes all the UserControl methods, properties, etc. in addition to its own specific members.
I've been thinking that one way to reduce the complexity of dealing with these UserControls is to access them through an interface. So instead of drag-and-drop to put the UserControl on the form, something like this in the constructor:
public class MyGiantForm
{
ICustomerName cName;
public MyForm()
{
InitializeComponent();
var uc = new SomeCustomerNameUserControl();
this.Controls.Add(uc);
cName = uc;
}
}
SomeCustomerNameUserControl implements ICustomerName, naturally, and ICustomerName contains the specific properties I really care about (say, FirstName and LastName). In this way I can refer to the UserControl through the cName member and, instead of being bowled over by all the UserControl members, I get only those in ICustomerName.
All well and good, but the problem is that if I do it this way, I can't see SomeCustomerNameUserControl in the Designer. Does anybody know I way I can do this but still see the UserControl on the form's design surface?
EDIT: One way to do this, which isn't overly complicated, is to put the controls on a base form. By default (in C#) the control members are private. Then I create a property for each control exposing it through the interface.
However, I'd be interested in some other way to do this, even if it's more complex. There seems to be some way to do it with IDesignerHost, but I can't find any applicable examples.
If SomeCustomerNameUserControl is defined like this:
class SomeCustomerNameUserControl : UserControl, ICustomerName
{
}
You can still drop this control in the designer (which creates someCustomerNameUserControl1) and do this whenever you need to:
ICustomerName cName = someCustomerNameUserControl1;
Maybe I'm missing something, but I think it's that simple.
There's a way to accomplish what you want -- hiding the members you don't want to see -- but make it apply automatically, without requiring others' cooperation in terms of them using a custom interface. You can do it by reintroducing all the members you don't want to see, and tagging them with attributes.
This is what Windows Forms does when, for example, a base-class property doesn't mean anything for a particular descendant. For example, Control has a Text property, but a Text property is meaningless on, say, a TabControl. So TabControl overrides the Text property, and adds attributes to its override saying "By the way, don't show my Text property in the Property Grid or in Intellisense." The property still exists, but since you never see it, it doesn't get in your way.
If you add an [EditorBrowsable(EditorBrowsableState.Never)] attribute to a member (property or method), then Intellisense will no longer show that member in its code-completion lists. If I'm understanding your question correctly, this is the big thing you're trying to achieve: make it hard for application code to use the member by accident.
For properties, you probably also want to add [Browsable(false)] to hide the property from the Property Grid, and [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] to prevent the designer from writing the property's value to the .designer.cs file.
These will make it very difficult to accidentally use the method/property. They're still not a guarantee, though. If you do need a guarantee, then throw in an [Obsolete] attribute too, and build with "Treat warnings as errors" -- then you're taken care of.
If the base member is virtual, you probably want to override it, and have your override simply call base. Don't throw an exception, since the overridden member will probably be called by the base class during the normal course of events. On the other hand, if the base member isn't virtual, then you want to use "new" instead of "override", and you can decide whether your implementation should call base, or just throw an exception -- nobody should be using your reintroduced member anyway, so it shouldn't matter.
public class Widget : UserControl
{
// The Text property is virtual in the base Control class.
// Override and call base.
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Obsolete("The Text property does not apply to the Widget class.")]
public override string Text
{
get { return base.Text; }
set { base.Text = value; }
}
// The CanFocus property is non-virtual in the base Control class.
// Reintroduce with new, and throw if anyone dares to call it.
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Obsolete("The CanFocus property does not apply to the Widget class.")]
public new bool CanFocus
{
get { throw new NotSupportedException(); }
}
// The Hide method is non-virtual in the base Control class.
// Note that Browsable and DesignerSerializationVisibility are
// not needed for methods, only properties.
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("The Hide method does not apply to the Widget class.")]
public new void Hide()
{
throw new NotSupportedException();
}
}
Yes, this is a fair bit of work, but you only have to do it once... per member, per class... umm, yeah. But if those base-class members really don't apply to your class, and having them there will cause confusion, then it may be worth going to the effort.
'I want ICustomerName to be the only option for accessing the UserControl's variable. The idea is that a developer doesn't have to "just remember" to cast it.'
The problem you are having is that you have two completely divergent uses for your form and the controls it hosts. There is no trick built into Visual Studio or winforms which solves this neatly for you. It may be possible, but there is a much cleaner and object oriented way to separate the two methods of interacting with the controls.
If you want to hide the fact that these objects inherit from UserControl, and just want to treat them as IDoSomeThingYouShouldDealWith, you need to separate the logic that deals with the presentation concerns (designer + UI logic) from your business logic.
Your form class, should rightly deal with the controls as UserControls, docking, anchoring etc etc, nothing special here. You should put all the logic that needs to deal with ICustomerName.FirstName = etc into a completely separate class. This class doesn't care or know about fonts and layout, it just knows that there is another instance that can present a customer name; or a DateTime as a 'date of birth choosing' control properly etc.
This is a really lame example, but I have to go right now. You should be able to get the idea covered here in more detail:
public interface ICustomerName
{
void ShowName(string theName);
}
public partial class Form1 : Form, ICustomerName
{
public Form1()
{
InitializeComponent();
}
#region ICustomerName Members
public void ShowName(string theName)
{
//Gets all controls that show customer names and sets the Text propert
//totheName
}
#endregion
}
//developers program logic into this class
public class Form1Controller
{
public Form1Controller(ICustomerName theForm) //only sees ICustomerName methods
{
//Look, i can't even see the Form object from here
theForm.ShowName("Amazing Name");
}
}
After you add the UserControl using the designer, you can set GenerateMember to false in the Properties window to suppress generation of a member.
You could then use some other technique in the constructor to assign your cName reference, e.g.:
foreach(Control control in this.Controls)
{
cName = control as ICustomerName;
if (cName != null) break;
}
cName would then be the only reference to the UserControl.
You could write an extension method that would allow you to return any controls on the form that implement an interface.
public static class FormExtensions
{
public static IDictionary<string, T> GetControlsOf<T>(this Form form)
where T: class
{
var result = new Dictionary<string, T>();
foreach (var control in form.Controls)
{
if ((control as T) != null)
result.Add((control as T).Tag, control as T);
}
return result;
}
}
Then in your form you could call it whereever you want by:
this.GetControlsOf<ICustomerName>()["NameOfControlHere"];
In the event that it returns more than one user control you would need to handle that some how, perhaps by adding Tag property to the interface to uniquely keep track of each user control or something, like so
public partial class UserControl1 : UserControl, ICustomerName
{
public string Tag { get { return this.Name; } }
}
You can then drag and drop the user controls onto your form from the designer. Tag will always return the name of your control, which will allow you to directly access the control through the IDictionary's interface. You're developers could put whatever unique identifier they want in the name of the control, and it would carry through to the interface.
Also, it should be noted that this approach will ALSO allow you to use this on ALL forms in your solution.
The only other thing you would need to do is set your GenerateMember to false.
you could as well do as Bob said but assign all your member variables in the constructor, then you have it in one place.
It almost seems like you want to implement a mediator pattern. Instead of having to deal with each of the bazillion UserControls directly, you'd interact with them through the mediator. Each mediator would define the slim interface you want to see from each control. This would reduce the overall complexity by making your design more explicit and concise. For example, you wouldn't need the 20 properties and 50 methods available on one of your controls. Instead you'd deal with the mediator for that control which defines the 2 properties and 5 methods you really care about. Everything would still show up in the designer, but other parts of your app would not be interacting with those controls -- they'd interact with the mediators.
One of the big advantages to this approach is it greatly simplifies your maintenance. If you decide the MyCrappyUserControl needs to be rewritten because the implementation is bad, you just need to update the mediator class for that control. All the other classes that interact with the control do so through the mediator and would be unchanged.
Ultimately it comes down to discipline: you and your team need to be disciplined enough to use the mediators/interfaces/whatever instead of the directly hitting the controls. Institute an over the shoulder code review by a leader programmer if your team is on the low end of the discipline scale.
Assume that MyUserControl is defined like this:
class MyUserControl : UserControl, IMyInterface
{
// ...
}
Then in your form, you should have something like this:
public class MyForm : Form
{
IMyInterface cName;
public MyForm()
{
InitializeComponent();
cName = new MyUserControl();
Controls.Add((UserControl)cName);
}
}
This way, cName is the only way to access this instance of our usercontrol.