Manually redrawing a custom control when WPF requests an arrangement - c#

I have a custom control that has a refresh method, something similar to this:
public class MyControl : Canvas
{
// Dependency property for "data" used to draw the control here
public void Refresh()
{
Children.Clear();
// Using data, draw the control
Children.Add(new Line(...));
Children.Add(new Rectangle(...));
// etc.
}
}
Right now, I have to call Refresh() manually each time I want the look of the control to update. My dependency properties are set up for FrameworkPropertyMetadataOptions.AffectsArrange, so WPF knows that modifying the properties will affect the arrangement of the control and that it should be redrawn. So here's the question:
What does WPF use to tell a custom control that it should be redrawn? Is it an event, or an override, and how should it be used? I've tried handling various events and overrides and nothing seems to work. So, what's the correct way to do this? I want to replace / wrap the Refresh() method above in something "automatic" that WPF will handle automatically.

Related

Notify on ArrangeOverride

I have an items control with custom panel. Based on this itemsControl I am writing an Behavior (Behavior)
What I need is whenever arrange override for my ItemsPanel is called my behaviour should get notified. In my behavior I have access to the itemsControl and the itemsPanel.
One way is I can raise an event from ItemsPanel override and subscribe it in my Behavior.
But if you there is a better solution please can you suggest?
Here is how I would try to do it:
Create a "fake" control
class ArrangeNotifier : Control
{
public event EventHandler OnArrange;
protected override ArrangeOverride(blabla)
{
(OnArrange??delegate{})(blabla);
}
}
On your "OnAttached" of your behavior, create a var myNotifier = new ArrangeNotifier() that you will add to the panel AttachedObject (which obliges your behavior to be a Behavior<Panel>)
Suscribe to myNotifier.OnArrange from your behavior, and do your stuff in the handler
Do not forget to remove your fake control in "OnDettached" of your behavior
[Edit] I misread your question, I guess that this was what you suggested :)
I dont see any another way.

What is the proper way to access Controls properties of User Controls in Winform?

I created this User Control:
I added that User Control to the main Form and now I want to customize it.
So I will have to add text to those 3 Buttons, text in Label, populate ListBox and setting Click Events for the buttons.
What is the proper way to do that?
I looked around on the web and apparently the way to do it is to add public properties in user control that would expose individual property of control that I need.
Something like:
public string Button1Text
{
get
{
return btn1.Text;
}
set
{
btn1.Text = value;
}
}
If I go this route, I would have to add quite a few public properties to this simple user control.
But isnt it easier just to expose whole control in user control like this?
public Button MyButton1
{
get { return this.btn1; }
set { this.btn1 = value; }
}
That way the Main Form can simply access control and its properties as they are needed.
First method is better from the perspective of encapsulation. Second method causes users (forms) of your control to depend on the view of your control, and this prevents changes to the view in the future.
The first bit of code is the correct way to do it. You will have to create a lot of them but it is the proper way to do it.
The first one is much better where you only create properties for each individual property of the button you wish to be able to access from the Parent control.
If you use the second way, then anyone who wishes to use your control will be able to move and resize individual controls inside your control. Then it really isn't a custom control anymore, but more of a panel that is harder to use than a panel. I can't think of any reason why to be able to allow the Parent to move around individual elements in a subcontrol.

Adding custom UI behavior to controls via a Component

In my project, I have several controls that display a set of points on the screen. I would like to provide "lasso selection" functionality for all of these controls. To do this, I wrote a class called "Lasso", which takes care of tracking mouse movements, displaying the lasso, raising an event when the lasso is closed, etc. So far so good. But, in order to use the lasso, I must write code like this:
public partial class MyControl : UserControl {
private Lasso lasso;
public MyControl() {
InitializeComponent();
lasso = new Lasso();
lasso.HookEvents(this);
}
}
The "lasso.HookEvents" method takes care of hooking up the lasso to the mouse events for the host control.
What I would like to do is somehow provide a way for people to simply drag the "Lasso" component from the Toolbox onto their UserControl or Form at design time, and not worry about writing any code themselves; the lasso should magically "just work". Is there a way to do that ? I tried extending my Lasso class from Component, but I couldn't figure out how to get the Designer to generate the "lasso.HookEvents(this)" invocation automatically.
If possible, just capture the mouse events in the Lasso object. If that's not possible or doesn't work: In your Lasso class, add a handler to the Loaded event, and in the handler run this.HookEvents(this.Parent);.

Windows Form - ListView - Removing lines between columns

I need to display a ListView in WinForms which should not have any lines between columns. I tried GridLines=false and also tried setting HeaderStyle to ColumnHeaderStyle.None. But this is not working. I want to remove the 2 vertical lines coming in the middle.
screenshot http://www.freeimagehosting.net/uploads/4bcee1f639.png
GridLine = False should work. (See Pramodh answer.) If not, you have something else wrong. If you setting this property in code, make sure the control's handle has been created. The method CreateControl and IsHandleCreated are helpful.
A common problem in C# that affects controls is accessing control properties in the form's constructor. Usually, the control handles are not created until they are "visible", which doesn't happen until the form is loaded. Therefore, if setting these properties in the form constructor, move the code to the Load event which is recommended by Microsoft.
Control.CreateControl Method
The CreateControl method forces a
handle to be created for the control
and its child controls. This method is
used when you need a handle
immediately for manipulation of the
control or its children; simply
calling a control's constructor does
not create the Handle.
CreateControl does not create a
control handle if the control's
Visible property is false. You can
either call the CreateHandle method or
access the Handle property to create
the control's handle regardless of the
control's visibility, but in this
case, no window handles are created
for the control's children.
just change the view into Details
and GridLines=false
like:
this.listView1.View = System.Windows.Forms.View.Details;
this.listView1.GridLines = false;

Subcontrols not visible in custom control derived from another control

I'm trying to create a custom control by deriving from a ZedGraphControl
I need to add a ProgressBar to the control, but I encountered some problems.
When I create a custom control and add both, ZedGraphCOntrol and ProgressBar to it, everything is OK:
MyCustomControl
{
ZedGraphControl
ProgressBar
}
All elemnets are visible and working as expected.
But I need to derive from ZGC and when I add a progress bar as a subcontrol of ZedGraphControl:
MyCustomControl : ZedGRaphControl
{
ProgressBar
}
The progress bar is not visible.
Is there any way to force the visibility of ProgressBar? Is it possible, that ZedGraphControl is not displaying its subcontrols? I tried do the same thing with a simple button and it's also not being displayed.
it seems that I solved the problem...
There must be a call to the InitializeComponent() method in the Control's constructor.
When I was creating a custom control, it was added by default by the VS. But while deriving from ZedGraphControl I was creating the constructor from scratch, and that's why the subcontrols were not visible.
So the question can be closed.

Categories

Resources