I have created a UserControl that has a ListView in it. The ListView is publicly accessible though a property. When I put the UserControl in a form and try to design the ListView though the property, the ListView stays that way until I compile again and it reverts back to the default state.
How do I get my design changes to stick for the ListView?
You need to decorate the ListView property with the DesignerSerializationVisibility attribute, like so:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ListView MyListView { get { return this.listView1; } }
This tells the designer's code generator to output code for it.
Fredrik is right, basically, when you need to enable the designer to persist the property to page so it can be instantiated at run time. There is only one way to do this, and that is to write its values to the ASPX page, which is then picked up by the runtime.
Otherwise, the control will simply revert to its default state each and every time.
Always keep in the back of your mind that the Page (and its contents) and the code are completely seperate in ASP.NET, they are hooked up at run time. This means that you dont get the nice code-behind designer support like you do in a WinForms app (where the form is an instance of an object).
Just so I'm clear, you've done something like this, right?
public ListView MyListView { get { return this.listView1; } }
So then you are accessing (at design time) the MyListView property on your UserControl?
I think if you want proper design-time support you're better off changing the "Modifier" property on the ListView itself (back on the original UserControl) to Public - that way you can modify the ListView directly on instances of the UserControl. I've had success doing that anyway.
Related
I'm writing a custom control from scratch (using Graphics) that will represent a set of columns each of which will have a list of cells, a lot like a grid view except this will have some custom features.
I'm having a hard time trying to figure out how to manage all the data binding problem. I'd like this grid to have a DataSource property which would basically need to be a jagged array (2D) of some objects each of which would need to be bound to a cell in the control. I'm still not sure which properties each of these objects will have, and so far I'm only using text. What I've been trying to do is have my model implement this interface:
public interface IDiagramDataSource
{
IBindingList Columns { get; }
}
and then have each column implement this:
public interface IDiagramColumnDataSource : INotifyPropertyChanged
{
IBindingList Cells { get; }
}
But I'm still having a hard time figuring out the best way to keep all these objects synchronized to the corresponding objects in my grid. I'd love to be able to put all the binding mess in an independent class but not sure how to do this. For now I'll just repaint the whole thing whenever there is any change in the data source, but I'd like to eventually be able to identify which property in which cell or which cell in which column have changed so that I can update only the necessary items in my grid.
Is there any pattern to follow when you want a control to be bindable to nested lists? I'm guessing there is since the DataGridView control does this.
I would suggest 2 option:
First suggestion has been suggested by HighCore, is to using WPF rather than custom winform object to do the job. WPF also has much more controls (ListView, even the generic ItemContainer, if I am not mistaken). Just implement the INotifyPropertyChanged at the ViewModel, then call OnPropertyChanged for the root (aggregate) element everytime you need to refresh the control. Don't forget to add UpdateSourceTrigger for ItemsSource Binding. WPF controls also has good implementation for drag and drop function.
I won't detail the implementation in WPF since there are much articles explaining it.
However if you think that it must be done with custom graphic drawing, then it is quite complex. You must trigger the method to re-draw your control graphic everytime any changes occured in the item list for it to take effect. It will be better if you can do partial update to your graphic (maybe using panels to trick it), but it is harder.
If not handled correctly (moreover if your control contains huge amount of data and/or control size) then it can causes some high memory loads.
I wish to create custom control with Items property.
Is it safe to return class ItemColection that implements IList<Item>, because i didn't saw this in any prebuilt controls?
What's the best way to implement this?
Yes, you can use pretty much anything. A Form is (just) a class.
That you don't see examples is mostly due to the fact that WinForms is a .NET 1.0 technology. Very few additions or changes since then.
And unless you need specific functionality, just keep it simple:
public IList<ItemType> ItemsCollection { get ... set ... }
There is no problem to create a property of type inherited from ILIst for a control. But if you are building a control it's better to make your property editable with PropertyGrid in design time. To make it editable you should create your own collection of items inherited from CollectionBase and create a property of that type.
Check out this article: Creating a Custom Collection for Use in a PropertyGrid
And after that don't forget to make your Items property editable in design time by setting appropriate attributes:
[Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public YourItemsCollection Items
{
get { ... }
set { ... }
}
I've adopted the following pattern for putting ListViewItems in a ListView with multiple columns (when I want to display information about a list of MyObject types), and I'm just curious to see if this is the best way to accomplish this task, or if there's anything more efficient and readable in code:
Create an inherited ListViewItem class that takes a MyObject object in the constructor - I'll call this MyObjectListViewItem - and a Refresh() method that clears and re-populates the ListViewItem subitems.
Populate the ListView with my new MyObjectListViewItem items.
example:
public MyObject MyObject { get; set; }
public MyObjectListViewItem(MyObject myObj)
{
MyObject = myObj;
this.Refresh();
}
public void Refresh()
{
this.SubItems.Clear();
this.Text = myObj.FirstColumnProperty;
this.SubItems.Add(myObj.SecondColumnProperty); // etc...
}
Suggestions? Better ways?
Have you considered using a BindingSource, or creating your own which implements IBindingListView? This keeps concerns about the data and its state scoped to the data itself and not on any controls which consume it. Since .NET controls are already built to work with BindingSources, you can take advantage of some more robust functionality. Instead of explicitly invoking a screen refresh, the control is simply responsible for responding to events raised by the binding source, and a controller that notifies whether the control is ready to be refreshed without forcing it.
Making ListViewItems that know how to build themselves is a good idea.
If you extend that idea a little, you make the columns know how to build each subitem, which also allows them to be able to automatically sort the ListView, support grouping and copy/drag and drop rows. This is just a few of the things that ObjectListView does for you.
ObjectListView is an open source wrapper around a .NET WinForms ListView control that makes the ListView much easier to use -- as well as adding some very nice new features and getting around some annoying bugs/limitations.
If you did like #Rex's idea of using a BindingSource, the ObjectListView project also provides a data-aware DataListView which is data bindable.
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".
I have a class ToolTipProvider
which has a method
string GetToolTip(UIElement element)
which will return a specific tooltip for the UIElement specified, based on various factors including properties of the UIElement itself and also looking up into documentation which can be changed dynamically. It will also probably run in a thread so when the form first fires up the tooltips will be something like the visual studio 'Document cache is still being constructed', then populated in the background.
I want to allow this to be used in any wpf form with the minimum effort for the developer. Essentially I want to insert an ObjectDataProvider resource into the Window.Resources to wrap my ToolTipProvider object, then I think I need to create a tooltip (called e.g. MyToolTipProvider) in the resources which references that ObjectDataProvider, then on any element which requires this tooltip functionality it would just be a case of ToolTip="{StaticResource MyToolTipProvider}"
however I can't work out a) how to bind the actual elemnt itself to the MethodParameters of the objectdataprovider, or b) how to force it to call the method each time the tooltip is opened.
Any ideas/pointers on the general pattern I need? Not looking for complete solution, just any ideas from those more experienced
Create a new user control which functions as a tool-tip view factory.
Use your control as the tool-tip, passing any data you need for the factory to your control using binding (e.g. the data, the containing control, ...)
<AnyControl>
<AnyControl.ToolTip>
<YourToolTipControl Content="{Binding}" />
</AnyControl.ToolTip>
</AnyControl>
Not calling myself an expert, but I'd probably attempt such a feature with an attached property. This would be attachable to any element in your UI and you can specify an event handler that gets access to the object to which the property is being attached as well as the value passed to the attached property. You can keep a reference to the element to which your attached property was attached and you would then be able to change the ToolTip whenever you want.