can't get value of trackbar on menu strip - c#

I've added a trackbar to menu strip manually because vs 2008 doesn't allow me to do.
However, i can't get the value of trackbar.
Form1.cs:
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.MenuStrip |
ToolStripItemDesignerAvailability.ContextMenuStrip)]
public class TrackBarMenuItem : ToolStripControlHost
{
private TrackBar trackBar;
public TrackBarMenuItem()
: base(new TrackBar())
{
this.trackBar = this.Control as TrackBar;
trackBar.TickFrequency = 1;
trackBar.Maximum = 255;
trackBar.LargeChange = 5;
trackBar.SmallChange = 2;
}
}
Form1.Designer.cs:
private TrackBarMenuItem trackBar1;
//
// trackBar1
//
this.trackBar1.Name = "trackBar1";
this.trackBar1.Size = new System.Drawing.Size(104, 25);
and this is how i need to use it:
private void trackBar1_Scroll(object sender, System.EventArgs e)
{
int valueB = trackBar1.Value;
pictureBox2.Image = Deneme(new Bitmap(pictureBox1.Image),valueB);
}
but i get this error:
Error 1 'goruntuIsleme2.Form1.TrackBarMenuItem' does not contain a
definition for 'Value' and no extension method 'Value' accepting a
first argument of type 'goruntuIsleme2.Form1.TrackBarMenuItem' could
be found (are you missing a using directive or an assembly reference?)
any ideas?

Expose the value of the internal Trackbar object as a property on your new TrackBarMenuItem class:
Value { get { return trackBar.Value; } set { trackBar.Value = value; } }

i am adding the solution i found. someone might need it:
[System.ComponentModel.DesignerCategory("code")]
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ContextMenuStrip | ToolStripItemDesignerAvailability.MenuStrip)]
public partial class ToolStripMenuItem : ToolStripControlHost
{
public ToolStripMenuItem()
: base(CreateControlInstance())
{
}
/// <summary>
/// Create a strongly typed property called TrackBar - handy to prevent casting everywhere.
/// </summary>
public TrackBar TrackBar
{
get
{
return Control as TrackBar;
}
}
/// <summary>
/// Create the actual control, note this is static so it can be called from the
/// constructor.
///
/// </summary>
/// <returns></returns>
private static Control CreateControlInstance()
{
TrackBar t = new TrackBar();
t.AutoSize = false;
t.Height = 16;
t.Maximum = 255;
// Add other initialization code here.
return t;
}
[DefaultValue(0)]
public int Value
{
get { return TrackBar.Value; }
set { TrackBar.Value = value; }
}
/// <summary>
/// Attach to events we want to re-wrap
/// </summary>
/// <param name="control"></param>
protected override void OnSubscribeControlEvents(Control control)
{
base.OnSubscribeControlEvents(control);
TrackBar trackBar = control as TrackBar;
trackBar.ValueChanged += new EventHandler(trackBar_ValueChanged);
}
/// <summary>
/// Detach from events.
/// </summary>
/// <param name="control"></param>
protected override void OnUnsubscribeControlEvents(Control control)
{
base.OnUnsubscribeControlEvents(control);
TrackBar trackBar = control as TrackBar;
trackBar.ValueChanged -= new EventHandler(trackBar_ValueChanged);
}
/// <summary>
/// Routing for event
/// TrackBar.ValueChanged -> ToolStripTrackBar.ValueChanged
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void trackBar_ValueChanged(object sender, EventArgs e)
{
// when the trackbar value changes, fire an event.
if (this.ValueChanged != null)
{
ValueChanged(sender, e);
}
}
// add an event that is subscribable from the designer.
public event EventHandler ValueChanged;
// set other defaults that are interesting
protected override Size DefaultSize
{
get
{
return new Size(200, 16);
}
}
}
if you add this to your code, you will be able to add trackbars as ToolStripMenuItem via Designer.

Does your class TrackBarMenuItem has a property called Value? If not, you have to add it.

Related

C# Color a button

My code creates multiple buttons with a certain color. When I click a button I want it to change to a HEX color and it works well. The problem is that when I click in another button, I want the previously selected button to go back to the default color scheme.
private void createButtons()
{
foreach (int axis_number in axis_sequence.number)
{
AxisSequence axis = new AxisSequence (axis_number);
axis.MouseLeftButtonDown += new MouseButtonEventHandler (axis_MouseLeftButtonDown);
axis_sequence.Children.Add (axis);
}
}
void axis_MouseLeftButtonDown (object sender, MouseButtonEventArgs e)
{
var converter = new System.Windows.Media.BrushConverter();
var brush_amob_gray = (System.Windows.Media.Brush)converter.ConvertFromString("#515151");
var brush_amob_orange = (System.Windows.Media.Brush)converter.ConvertFromString("#FF8C00");
((AxisSequence)sender).change_canvas = brush_amob_orange;
((AxisSequence)sender).change_text_color = System.Windows.Media.Brushes.Black;
//When I click another button I wanted to all the others to the default Colors.
AXIS SEQUENCE:
public partial class AxisSequence : UserControl
{
/// <summary>
///
/// </summary>
/// <param name="numero_eixo"></param>
public AxisSequence (int numero_eixo)
{
try
{
InitializeComponent();
Value.Content = numero_eixo.ToString();
}
catch (System.Exception ex)
{
System.Windows.MessageBox.Show(ex.ToString());
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public int get_numero_eixo ()
{
return Int32.Parse (Value.Content.ToString());
}
/// <summary>
///
/// </summary>
public System.Windows.Media.Brush change_canvas { get { return canvas.Background; } set { canvas.Background = value; } }
/// <summary>
///
/// </summary>
public System.Windows.Media.Brush change_text_color { get { return Value.Foreground; } set { Value.Foreground = value; } }
}

Can put xml reader function into D3drenderer.cs?

Below is the standard d3drenderer.cs file coding:
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;
using System.Xml.Linq;
namespace WPFMediaKit.DirectShow.Controls
{
/// <summary>
/// The D3DRenderer class provides basic functionality needed
/// to render a D3D surface. This class is abstract.
/// </summary>
public abstract class D3DRenderer : FrameworkElement
{
private string workingDirectory = AppDomain.CurrentDomain.BaseDirectory;
/// <summary>
/// The D3DImage used to render video
/// </summary>
private D3DImage m_d3dImage;
/// <summary>
/// The Image control that has the source
/// to the D3DImage
/// </summary>
private Image m_videoImage;
/// <summary>
/// We keep reference to the D3D surface so
/// we can delay loading it to avoid a black flicker
/// when loading new media
/// </summary>
private IntPtr m_pBackBuffer = IntPtr.Zero;
/// <summary>
/// Flag to tell us if we have a new D3D
/// Surface available
/// </summary>
private bool m_newSurfaceAvailable;
/// <summary>
/// A weak reference of D3DRenderers that have been cloned
/// </summary>
private readonly List<WeakReference> m_clonedD3Drenderers = new List<WeakReference>();
/// <summary>
/// Backing field for the RenderOnCompositionTargetRendering flag.
/// </summary>
private bool m_renderOnCompositionTargetRendering;
/// <summary>
/// Temporary storage for the RenderOnCompositionTargetRendering flag.
/// This is used to remember the value for when the control is loaded and unloaded.
/// </summary>
private bool m_renderOnCompositionTargetRenderingTemp;
#region Stretch
public static readonly DependencyProperty StretchProperty =
DependencyProperty.Register("Stretch", typeof(Stretch), typeof(D3DRenderer),
new FrameworkPropertyMetadata(Stretch.Uniform,
new PropertyChangedCallback(OnStretchChanged)));
/// <summary>
/// Defines what rules are applied to the stretching of the video
/// </summary>
public Stretch Stretch
{
get { return (Stretch)GetValue(StretchProperty); }
set { SetValue(StretchProperty, value); }
}
private static void OnStretchChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((D3DRenderer)d).OnStretchChanged(e);
}
private void OnStretchChanged(DependencyPropertyChangedEventArgs e)
{
m_videoImage.Stretch = (Stretch) e.NewValue;
}
#endregion
#region IsRenderingEnabled
public static readonly DependencyProperty IsRenderingEnabledProperty =
DependencyProperty.Register("IsRenderingEnabled", typeof(bool), typeof(D3DRenderer),
new FrameworkPropertyMetadata(true));
/// <summary>
/// Enables or disables rendering of the video
/// </summary>
public bool IsRenderingEnabled
{
get { return (bool)GetValue(IsRenderingEnabledProperty); }
set { SetValue(IsRenderingEnabledProperty, value); }
}
#endregion
#region NaturalVideoHeight
private static readonly DependencyPropertyKey NaturalVideoHeightPropertyKey
= DependencyProperty.RegisterReadOnly("NaturalVideoHeight", typeof(int), typeof(MediaElementBase),
new FrameworkPropertyMetadata(0));
public static readonly DependencyProperty NaturalVideoHeightProperty
= NaturalVideoHeightPropertyKey.DependencyProperty;
/// <summary>
/// Gets the natural pixel height of the current media.
/// The value will be 0 if there is no video in the media.
/// </summary>
public int NaturalVideoHeight
{
get { return (int)GetValue(NaturalVideoHeightProperty); }
}
/// <summary>
/// Internal method to set the read-only NaturalVideoHeight DP
/// </summary>
protected void SetNaturalVideoHeight(int value)
{
SetValue(NaturalVideoHeightPropertyKey, value);
}
#endregion
#region NaturalVideoWidth
private static readonly DependencyPropertyKey NaturalVideoWidthPropertyKey
= DependencyProperty.RegisterReadOnly("NaturalVideoWidth", typeof(int), typeof(MediaElementBase),
new FrameworkPropertyMetadata(0));
public static readonly DependencyProperty NaturalVideoWidthProperty
= NaturalVideoWidthPropertyKey.DependencyProperty;
/// <summary>
/// Gets the natural pixel width of the current media.
/// The value will be 0 if there is no video in the media.
/// </summary>
public int NaturalVideoWidth
{
get { return (int)GetValue(NaturalVideoWidthProperty); }
}
/// <summary>
/// Internal method to set the read-only NaturalVideoWidth DP
/// </summary>
protected void SetNaturalVideoWidth(int value)
{
SetValue(NaturalVideoWidthPropertyKey, value);
}
#endregion
#region HasVideo
private static readonly DependencyPropertyKey HasVideoPropertyKey
= DependencyProperty.RegisterReadOnly("HasVideo", typeof(bool), typeof(MediaElementBase),
new FrameworkPropertyMetadata(false));
public static readonly DependencyProperty HasVideoProperty
= HasVideoPropertyKey.DependencyProperty;
/// <summary>
/// Is true if the media contains renderable video
/// </summary>
public bool HasVideo
{
get { return (bool)GetValue(HasVideoProperty); }
}
/// <summary>
/// Internal method for setting the read-only HasVideo DP
/// </summary>
protected void SetHasVideo(bool value)
{
SetValue(HasVideoPropertyKey, value);
}
#endregion
protected D3DRenderer()
{
InitializeD3DVideo();
/* Hook into the framework events */
Loaded += D3DRenderer_Loaded;
Unloaded += D3DRenderer_Unloaded;
}
/// <summary>
/// Handler for when the D3DRenderer is unloaded
/// </summary>
private void D3DRenderer_Unloaded(object sender, RoutedEventArgs e)
{
/* Remember what the property value was */
m_renderOnCompositionTargetRenderingTemp = RenderOnCompositionTargetRendering;
/* Make sure to unhook the static event hook because we are unloading */
RenderOnCompositionTargetRendering = false;
}
/// <summary>
/// Handler for when the D3DRenderer is loaded
/// </summary>
private void D3DRenderer_Loaded(object sender, RoutedEventArgs e)
{
/* Restore the property's value */
RenderOnCompositionTargetRendering = m_renderOnCompositionTargetRenderingTemp;
}
/// <summary>
/// Initializes the D3DRenderer control
/// </summary>
protected virtual void InitializeD3DVideo()
{
if (m_videoImage != null)
return;
/* Create our Image and it's D3DImage source */
m_videoImage = new Image();
m_d3dImage = new D3DImage();
/* We hook into this event to handle when a D3D device is lost */
D3DImage.IsFrontBufferAvailableChanged += D3DImage_IsFrontBufferAvailableChanged;
/* Set our default stretch value of our video */
m_videoImage.Stretch = (Stretch)StretchProperty.DefaultMetadata.DefaultValue;
var activeProfiles = XElement.Load(workingDirectory + "ProfilesDisplay.xml");
var a = activeProfiles.Element("_nABC").Value;
/* Our source of the video image is the D3DImage */
m_videoImage.Source = D3DImage;
/* Register the Image as a visual child */
AddVisualChild(m_videoImage);
}
/// <summary>
/// This should only fire when a D3D device is lost
/// </summary>
private void D3DImage_IsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (!D3DImage.IsFrontBufferAvailable)
return;
/* Flag that we have a new surface, even
* though we really don't */
m_newSurfaceAvailable = true;
/* Force feed the D3DImage the Surface pointer */
SetBackBufferInternal(m_pBackBuffer);
}
protected override Size MeasureOverride(Size availableSize)
{
m_videoImage.Measure(availableSize);
return m_videoImage.DesiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
m_videoImage.Arrange(new Rect(finalSize));
return finalSize;
}
protected override int VisualChildrenCount
{
get
{
return 1;
}
}
protected override Visual GetVisualChild(int index)
{
if (index > 0)
throw new IndexOutOfRangeException();
return m_videoImage;
}
protected D3DImage D3DImage
{
get
{
return m_d3dImage;
}
}
protected Image VideoImage
{
get
{
return m_videoImage;
}
}
/// <summary>
/// Renders the video with WPF's rendering using the CompositionTarget.Rendering event
/// </summary>
protected bool RenderOnCompositionTargetRendering
{
get
{
return m_renderOnCompositionTargetRendering;
}
set
{
/* If it is being set to true and it was previously false
* then hook into the event */
if (value && !m_renderOnCompositionTargetRendering)
CompositionTarget.Rendering += CompositionTarget_Rendering;
else if(!value)
CompositionTarget.Rendering -= CompositionTarget_Rendering;
m_renderOnCompositionTargetRendering = value;
m_renderOnCompositionTargetRenderingTemp = value;
}
}
private void CompositionTarget_Rendering(object sender, EventArgs e)
{
InternalInvalidateVideoImage();
}
/// <summary>
/// Used as a clone for a D3DRenderer
/// </summary>
private class ClonedD3DRenderer : D3DRenderer
{}
/// <summary>
/// Creates a clone of the D3DRenderer. This is a work for the visual
/// brush not working cross-threaded
/// </summary>
/// <returns></returns>
public D3DRenderer CloneD3DRenderer()
{
var renderer = new ClonedD3DRenderer();
lock(m_clonedD3Drenderers)
{
m_clonedD3Drenderers.Add(new WeakReference(renderer));
}
renderer.SetBackBuffer(m_pBackBuffer);
return renderer;
}
/// <summary>
/// Cleans up any dead references we may have to any cloned renderers
/// </summary>
private void CleanZombieRenderers()
{
lock(m_clonedD3Drenderers)
{
var deadObjects = new List<WeakReference>();
for (int i = 0; i < m_clonedD3Drenderers.Count; i++)
{
if (!m_clonedD3Drenderers[i].IsAlive)
deadObjects.Add(m_clonedD3Drenderers[i]);
}
foreach(var deadGuy in deadObjects)
{
m_clonedD3Drenderers.Remove(deadGuy);
}
}
}
/// <summary>
/// Configures D3DImage with a new surface. The back buffer is
/// not set until we actually receive a frame, this way we
/// can avoid a black flicker between media changes
/// </summary>
/// <param name="backBuffer">The unmanaged pointer to the Direct3D Surface</param>
protected void SetBackBuffer(IntPtr backBuffer)
{
/* We only do this if target rendering is enabled because we must use an Invoke
* instead of a BeginInvoke to keep the Surfaces in sync and Invoke could be dangerous
* in other situations */
if(RenderOnCompositionTargetRendering)
{
if (!D3DImage.Dispatcher.CheckAccess())
{
D3DImage.Dispatcher.Invoke((Action)(() => SetBackBuffer(backBuffer)), DispatcherPriority.Render);
return;
}
}
/* Flag a new surface */
m_newSurfaceAvailable = true;
m_pBackBuffer = backBuffer;
/* Make a special case for target rendering */
if (RenderOnCompositionTargetRendering)
{
SetBackBufferInternal(m_pBackBuffer);
}
SetBackBufferForClones();
}
/// <summary>
/// Sets the backbuffer for any cloned D3DRenderers
/// </summary>
private void SetBackBufferForClones()
{
lock (m_clonedD3Drenderers)
{
CleanZombieRenderers();
foreach (var rendererRef in m_clonedD3Drenderers)
{
var renderer = rendererRef.Target as D3DRenderer;
if (renderer != null)
renderer.SetBackBuffer(m_pBackBuffer);
}
}
}
/// <summary>
/// Configures D3DImage with a new surface. This happens immediately
/// </summary>
private void SetBackBufferInternal(IntPtr backBuffer)
{
/* Do nothing if we don't have a new surface available */
if (!m_newSurfaceAvailable)
return;
if(!D3DImage.Dispatcher.CheckAccess())
{
D3DImage.Dispatcher.BeginInvoke((Action)(() => SetBackBufferInternal(backBuffer)));
return;
}
/* We have this around a try/catch just in case we
* lose the device and our Surface is invalid. The
* try/catch may not be needed, but testing needs
* to take place before it's removed */
try
{
D3DImage.Lock();
D3DImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, backBuffer);
D3DImage.Unlock();
SetNaturalWidthHeight();
}
catch (Exception)
{ }
/* Clear our flag, so this won't be ran again
* until a new surface is sent */
m_newSurfaceAvailable = false;
}
private void SetNaturalWidthHeight()
{
SetNaturalVideoHeight(m_d3dImage.PixelHeight);
SetNaturalVideoWidth(m_d3dImage.PixelWidth);
}
protected void InvalidateVideoImage()
{
if (!m_renderOnCompositionTargetRendering)
InternalInvalidateVideoImage();
}
/// <summary>
/// Invalidates the entire Direct3D image, notifying WPF to redraw
/// </summary>
protected void InternalInvalidateVideoImage()
{
/* Ensure we run on the correct Dispatcher */
if(!D3DImage.Dispatcher.CheckAccess())
{
D3DImage.Dispatcher.BeginInvoke((Action)(() => InvalidateVideoImage()));
return;
}
/* If there is a new Surface to set,
* this method will do the trick */
SetBackBufferInternal(m_pBackBuffer);
/* Only render the video image if possible, or if IsRenderingEnabled is true */
if (D3DImage.IsFrontBufferAvailable && IsRenderingEnabled && m_pBackBuffer != IntPtr.Zero)
{
try
{
/* Invalidate the entire image */
D3DImage.Lock();
D3DImage.AddDirtyRect(new Int32Rect(0, /* Left */
0, /* Top */
D3DImage.PixelWidth, /* Width */
D3DImage.PixelHeight /* Height */));
D3DImage.Unlock();
}
catch
{ }
}
/* Invalidate all of our cloned D3DRenderers */
InvalidateClonedVideoImages();
}
/// <summary>
/// Invalidates any possible cloned renderer we may have
/// </summary>
private void InvalidateClonedVideoImages()
{
lock(m_clonedD3Drenderers)
{
CleanZombieRenderers();
foreach(var rendererRef in m_clonedD3Drenderers)
{
var renderer = rendererRef.Target as D3DRenderer;
if(renderer != null)
renderer.InvalidateVideoImage();
}
}
}
}
}
In the InitializeD3DVideo() function, I try to read a xml file from a location from the harddisk. But it can't be done.
Is it that the d3drenderer.cs cannot read from a xml file? I just want to read a value from _nABC of the xml file.
This has nothing to do with the D3DRenderer.
The path to the XML file is wrong. There is a '/' (or '\') missing between the workingDirectory and the + "ProfilesDisplay.xml".
If you don't know your path strings, the best method to combine these is System.IO.Path.Combine.

Custom C# button's DialogResult doesn't work correctly on modal form

Having a little trouble making a Winforms ImageButton class (C#). My ImageButton class implements the IButtonControl interface but when I add it to a form, and set the button's DialogResult to 'OK' , and then call ShowDialog() on the form, pressing the button does not close the form and return the DialogResult, as the normal Winforms Button control does.
Here's my implementation of ImageButton, feel free to do whatever you like with it.
/// <summary>
/// A control that displays an image and responds to mouse clicks on the image.
/// </summary>
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[Designer(typeof(ImageButtonDesigner))]
[ToolboxItem(typeof(ImageButtonToolboxItem))]
public class ImageButton : PictureBox, IButtonControl, INotifyPropertyChanged
{
#region Constructors
/// <summary>
/// Initializes a new instance of the ImageButton class using the default initial values.
/// </summary>
public ImageButton()
{
DoubleBuffered = true;
BackColor = Color.Transparent;
SizeMode = PictureBoxSizeMode.AutoSize;
}
#endregion
#region Properties
/// <summary>
/// Backing field for the DialogResult property.
/// </summary>
private DialogResult dialogResult;
/// <summary>
/// Gets or sets a value that is returned to the parent form when the button is clicked.
/// </summary>
[Category("Behavior")]
[Description("The dialog-box result produced in a modal form by clicking the button")]
public DialogResult DialogResult
{
get
{
return dialogResult;
}
set
{
if (Enum.IsDefined(typeof(DialogResult), value))
dialogResult = value;
else
throw new InvalidEnumArgumentException("value", (int)value, typeof(DialogResult));
}
}
/// <summary>
/// Backing field for the Idle property.
/// </summary>
private Image idle;
/// <summary>
/// The image that will be displayed on the control when the mouse is not over a visible part of it.
/// </summary>
[Category("Appearance")]
[Description("The image that will be displayed on the Control when the mouse is not over a visible part of it.")]
public Image Idle
{
get
{
return idle;
}
set
{
idle = value;
NotifyPropertyChanged();
}
}
/// <summary>
/// Backing field for the Mouseover property
/// </summary>
private Image mouseover;
/// <summary>
/// The image that will be displayed on the control when the mouse is over a visible part of it.
/// </summary>
[Category("Appearance")]
[Description("The image that will be displayed on the control when the mouse is over a visible part of it.")]
public Image Mouseover
{
get { return mouseover; }
set
{
mouseover = value;
NotifyPropertyChanged();
}
}
/// <summary>
/// Backing field for the Mousedown property
/// </summary>
private Image mousedown;
/// <summary>
/// The image that will be displayed on the control when the left mouse button is held down and the mouse is over a visible part of it.
/// </summary>
[Category("Appearance")]
[Description("The image that will be displayed on the control when the left mouse button is held down and the mouse is over a visible part of it.")]
public Image Mousedown
{
get { return mousedown; }
set
{
mousedown = value;
NotifyPropertyChanged();
}
}
/// <summary>
/// Gets or sets the text associated with the control.
/// </summary>
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Category("Appearance")]
[Description("The text associated with the control.")]
public override string Text
{
get
{
return base.Text;
}
set
{
base.Text = value;
}
}
/// <summary>
/// Gets or sets the font of the text displayed by the control.
/// </summary>
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Category("Appearance")]
[Description("The font used to display text in the control.")]
public override Font Font
{
get
{
return base.Font;
}
set
{
base.Font = value;
}
}
/// <summary>
/// Gets or sets the image that is displayed by the PictureBox.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[Category("Appearance")]
[Description("The image displayed in the PictureBox.")]
new public Image Image
{
get
{
return base.Image;
}
set
{
base.Image = value;
}
}
/// <summary>
/// Backing field for the ButtonState property.
/// </summary>
private ButtonStates buttonState = ButtonStates.None;
/// <summary>
/// The current state of the button.
/// </summary>
private ButtonStates ButtonState
{
get { return buttonState; }
set
{
buttonState = value;
NotifyPropertyChanged();
}
}
/// <summary>
/// Gets the default size of the control.
/// </summary>
protected override Size DefaultSize
{
get
{
return new Size(75, 23);
}
}
#endregion
#region Enums
/// <summary>
/// Specifies the current state of a button.
/// </summary>
[Flags]
private enum ButtonStates : byte
{
/// <summary>
///
/// </summary>
[Description("")]
None = 0,
/// <summary>
///
/// </summary>
[Description("")]
Default = 1 << 0,
/// <summary>
///
/// </summary>
[Description("")]
Mouseover = 1 << 1,
/// <summary>
///
/// </summary>
[Description("")]
Mousedown = 1 << 2
}
#endregion
#region Events
/// <summary>
/// Occurs when a property value changes.
/// </summary>
[Category("Property Changed")]
[Description("Occurs when a property value changes.")]
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Methods
/// <summary>
/// Raises the System.ComponentModel.PropertyChanged event.
/// </summary>
/// <param name="propertyName">the name of the property that changed.</param>
protected virtual void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
if (propertyName == "Idle")
Image = Idle;
}
/// <summary>
/// Notifies the button whether it is the default button so that it can adjust its appearance accordingly.
/// </summary>
/// <param name="value">true if the button is to have the appearance of the default button; otherwise, false.</param>
public void NotifyDefault(bool value)
{
ButtonState = value ? ButtonState | ButtonStates.Default : ButtonState & ~ButtonStates.Default;
}
/// <summary>
/// Generates a Click event for a button.
/// </summary>
public void PerformClick()
{
if (CanSelect)
{
OnClick(EventArgs.Empty);
}
}
/// <summary>
/// Raises the System.Windows.Control.TextChanged event.
/// </summary>
/// <param name="e">A System.EventArgs that contains the event data.</param>
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
Refresh();
}
/// <summary>
/// Raises the System.Windows.Forms.Paint event.
/// </summary>
/// <param name="pe">A PaintEventArgs that contains the event data.</param>
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
if ((!string.IsNullOrEmpty(Text)) && (pe != null) && (base.Font != null))
{
SolidBrush drawBrush = new SolidBrush(base.ForeColor);
// Calculate the size of the text that will be drawn onto the control.
SizeF drawStringSize = pe.Graphics.MeasureString(base.Text, base.Font);
// The registration point used to draw the text.
PointF drawPoint;
if (base.Image != null)
drawPoint = new PointF(base.Image.Width / 2 - drawStringSize.Width / 2, base.Image.Height / 2 - drawStringSize.Height / 2);
else
drawPoint = new PointF(base.Width / 2 - drawStringSize.Width / 2, base.Height / 2 - drawStringSize.Height / 2);
pe.Graphics.DrawString(base.Text, base.Font, drawBrush, drawPoint);
}
}
/// <summary>
/// Raises the System.Windows.Forms.MouseEnter event.
/// </summary>
/// <param name="e">A System.EventArgs that contains the event data.</param>
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
ButtonState |= ButtonStates.Mouseover;
Image = Mouseover;
}
/// <summary>
/// Raises the System.Windows.Forms.MouseLeave event.
/// </summary>
/// <param name="e">A System.EventArgs that contains the event data.</param>
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
ButtonState &= ~ButtonStates.Mouseover;
Image = Idle;
}
/// <summary>
/// Raises the System.Windows.Forms.MouseDown event.
/// </summary>
/// <param name="e">A System.Windows.Forms.MouseEventArgs that contains the event data.</param>
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
ButtonState |= ButtonStates.Mousedown;
Image = Mousedown;
}
/// <summary>
/// Raises the System.Windows.Forms.MouseUp event.
/// </summary>
/// <param name="e">A System.Windows.Forms.MouseEventArgs that contains the event data.</param>
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
ButtonState &= ~ButtonStates.Mousedown;
Image = ((ButtonState & ButtonStates.Mouseover) != 0) ? Mouseover : idle;
}
#endregion
}
[Serializable]
internal class ImageButtonToolboxItem : ToolboxItem
{
public ImageButtonToolboxItem() : base(typeof(ImageButton)) { }
protected ImageButtonToolboxItem(SerializationInfo info, StreamingContext context)
{
Deserialize(info, context);
}
protected override IComponent[] CreateComponentsCore(IDesignerHost host)
{
ImageButton imageButton = (ImageButton)host.CreateComponent(typeof(ImageButton));
Assembly assembly = Assembly.GetAssembly(typeof(ImageButton));
using (Stream streamMouseover = assembly.GetManifestResourceStream("Mvc.Mouseover.png"))
using (Stream streamMousedown = assembly.GetManifestResourceStream("Mvc.Mousedown.png"))
using (Stream streamIdle = assembly.GetManifestResourceStream("Mvc.Idle.png"))
{
imageButton.Idle = Image.FromStream(streamIdle);
imageButton.Mouseover = Image.FromStream(streamMouseover);
imageButton.Mousedown = Image.FromStream(streamMousedown);
}
return new IComponent[] { imageButton };
}
}
internal class ImageButtonDesigner : ControlDesigner
{
protected override void PostFilterAttributes(System.Collections.IDictionary attributes)
{
base.PostFilterAttributes(attributes);
Attribute dockingBehaviour = new DockingAttribute(DockingBehavior.Never);
attributes[typeof(DockingAttribute)] = dockingBehaviour;
}
public override SelectionRules SelectionRules
{
get
{
return SelectionRules.Moveable;
}
}
}
Sorry about the messy toolbox item and designer code..
My Question is, Does there need to be anything special implementation wise to get a button control to work on a modal form (in the same way the normal button does)
(NB. The Form's BorderStyle property is set to None, don't know if thats important)
Thanks, in advance!
You need to actually apply the assigned DialogResult property, it is not automatic. Do so by overriding the OnClick() method:
protected override void OnClick(EventArgs e) {
var form = this.FindForm();
if (form != null) form.DialogResult = dialogResult;
base.OnClick(e);
}
Technically you should also notify accessibility clients of the state change, it isn't clear at all whether you care about this. It tends to be skipped for custom controls but you generally ought to. Insert these statements before the base.OnClick() call:
base.AccessibilityNotifyClients(AccessibleEvents.StateChange, -1);
base.AccessibilityNotifyClients(AccessibleEvents.NameChange, -1);

Implementing an observer pattern with winforms

I have one collection of objects that many of my forms (using WeifenLuo.WinFormsUI.Docking) need to interact with.
i.e. If the collection has an addition (or deletion) made in one form, then the other forms respond by refreshing their views.
Obviously, an observer pattern would be a good candidate here. However, I am having issues trying to implement this in my program.
First, it seemed best to create an observer class for my collection like so:
public class DataCollectionObserver : Form
{
internal static void DataCollectionRegister(DataCollection dataCollection)
{
dataCollection.ImageAdded += new EventHandler(dataAdded);
dataCollection.ImageRemoved += new EventHandler(dataRemoved);
dataCollection.ImageIndexChanged += new EventHandler(dataIndexChanged);
dataCollection.ImageListCleared += new EventHandler(dataListCleared);
}
internal static void DataCollectionUnRegister(DataCollection dataCollection)
{
dataCollection.ImageAdded -= new EventHandler(dataAdded);
dataCollection.ImageRemoved -= new EventHandler(dataRemoved);
dataCollection.ImageIndexChanged -= new EventHandler(dataIndexChanged);
dataCollection.ImageListCleared -= new EventHandler(dataListCleared);
}
internal static void dataAdded(object sender, EventArgs e) {}
internal static void dataRemoved(object sender, EventArgs e) {}
internal static void dataIndexChanged(object sender, EventArgs e) {}
internal static void dataListCleared(object sender, EventArgs e) {}
}
Then override the base event handlers in the subclassed forms?
But, I cannot do this and use the WeifenLuo.WinFormsUI.Docking library...
Well, I could have DataCollectionObserver inherit DockContent from WeifenLuo.WinFormsUI.Docking, but that creates a situation where I need to have two DataCollectionObserver classes -
one which inherits Form and another that inherits DockContent :-[
or, I could make the DataCollectionObserver an Interface, but that still leaves me with duplicate code laying about...
So, does anyone have a suggestion here? Am I missing something obvious, or is this a situation where duplication of code 'must be done' for the sake of simplicity?
Edit://
I am not having problems getting notification in my forms. As a matter of fact, the whole thing is working right now. The reason that I am asking is because the whole thing "smells" due to the block copy and paste of code in these four different forms that I have which subscribe to the collection events and unsubscribe on Form.Closing().
What I would like to do is implement the behavior that I have copied and pasted to these four forms in one place and have the forms that should receive collection change notifications implement that behavior as needed.
Hope that makes things clearer?
FWIW, this is my collection class:
using System;
using System.Collections;
using System.Reflection;
namespace MyNameSpace.Collections
{
/// <summary>
/// Generic Collection of Objects with Events
/// </summary>
public class CollectionWithEvents<T> : CollectionBase
{
public bool SuppressEventNotification
{
get;
set;
}
public CollectionWithEvents()
{
SuppressEventNotification = false;
}
#region Events
/// <summary>
/// Raises before an item is added to the list.
/// </summary>
public event EventHandler<ItemEventArgs<T>> BeforeItemAdded;
/// <summary>
/// Raises when an item is added to the list.
/// </summary>
public event EventHandler<ItemEventArgs<T>> ItemAdded;
/// <summary>
/// Raises before a collection of items is added to the list.
/// </summary>
public event EventHandler<ItemsEventArgs<T>> BeforeItemsAdded;
/// <summary>
/// Raises when a collection of items is added to the list.
/// </summary>
public event EventHandler<ItemsEventArgs<T>> ItemsAdded;
/// <summary>
/// Raises before an item is changed in the list.
/// </summary>
public event EventHandler<ItemEventArgs<T>> BeforeItemChanged;
/// <summary>
/// Raises when an item is changed in the list.
/// </summary>
public event EventHandler<ItemEventArgs<T>> ItemChanged;
/// <summary>
/// Raises before an item is removed from the list.
/// </summary>
public event EventHandler<ItemEventArgs<T>> BeforeItemRemoved;
/// <summary>
/// Raises when an item is removed from the list.
/// </summary>
public event EventHandler<ItemEventArgs<T>> ItemRemoved;
/// <summary>
/// Raises when the items are cleared from the list.
/// </summary>
public event EventHandler<EventArgs> ItemsCleared;
#endregion
public T this[int index]
{
get { return (T)this.List[index]; }
set
{
if (!SuppressEventNotification)
{
OnBeforeItemChanged(this, new ItemEventArgs<T>(value));
}
this.List[index] = value;
if (!SuppressEventNotification)
{
OnItemChanged(this, new ItemEventArgs<T>(value));
}
}
}
public int Add(T item)
{
if (!SuppressEventNotification)
{
OnBeforeItemAdded(this, new ItemEventArgs<T>(item));
}
int retValue = this.List.Add(item);
if (!SuppressEventNotification)
{
OnItemAdded(this, new ItemEventArgs<T>(item));
}
return retValue;
}
public void AddRange(Collection<T> collection)
{
T[] tmp = new T[collection.Count];
collection.CopyTo(tmp, 0);
AddRange(tmp);
}
public void AddRange(T[] collection)
{
if (!SuppressEventNotification)
{
OnBeforeItemsAdded(this, new ItemsEventArgs<T>(collection));
}
this.AddRange(collection);
if (!SuppressEventNotification)
{
OnItemsAdded(this, new ItemsEventArgs<T>(collection));
}
}
public bool Contains(T item)
{
return this.List.Contains(item);
}
public void CopyTo(Array array, int index)
{
this.List.CopyTo(array, index);
}
public int IndexOf(T item)
{
return this.List.IndexOf(item);
}
public void Insert(int index, T item)
{
this.List.Insert(index, item);
}
public void Remove(T item)
{
if (!SuppressEventNotification)
{
OnBeforeItemRemoved(this, new ItemEventArgs<T>(item));
}
T tmp = (T)item;
this.List.Remove(item);
if (!SuppressEventNotification)
{
OnItemRemoved(this, new ItemEventArgs<T>(tmp));
}
tmp = default(T);
}
public void Sort(string Property, Common.SortOrder Order)
{
Common.GenericComparer genericComparer = new Common.GenericComparer(Property, Order);
this.InnerList.Sort(genericComparer);
}
#region Event Methods
/// <summary>
/// Raised before an Item is added to the list.
/// </summary>
/// <param name="sender">object</param>
/// <param name="e">ItemEventArgs</param>
protected virtual void OnBeforeItemAdded(object sender, ItemEventArgs<T> e)
{
if (BeforeItemAdded != null)
{
BeforeItemAdded(sender, e);
}
}
/// <summary>
/// Raised when an Item is added to the list.
/// </summary>
/// <param name="sender"></param>
/// <param name="e">ItemEventArgs</param>
protected virtual void OnItemAdded(object sender, ItemEventArgs<T> e)
{
if (ItemAdded != null)
{
ItemAdded(sender, e);
}
}
/// <summary>
/// Raised before a collection of Items is added to the list.
/// </summary>
/// <param name="sender">object</param>
/// <param name="e">ItemEventArgs</param>
protected virtual void OnBeforeItemsAdded(object sender, ItemsEventArgs<T> e)
{
if (BeforeItemsAdded != null)
{
BeforeItemsAdded(sender, e);
}
}
/// <summary>
/// Raised when a collection of Items is added to the list.
/// </summary>
/// <param name="sender"></param>
/// <param name="e">ItemEventArgs</param>
protected virtual void OnItemsAdded(object sender, ItemsEventArgs<T> e)
{
if (ItemsAdded != null)
{
ItemsAdded(sender, e);
}
}
/// <summary>
/// Raised before an Item is changed to the list.
/// </summary>
/// <param name="sender"></param>
/// <param name="e">GenericItemEventArgs</param>
protected virtual void OnBeforeItemChanged(object sender, ItemEventArgs<T> e)
{
if (BeforeItemChanged != null)
{
BeforeItemChanged(sender, e);
}
}
/// <summary>
/// Raised when an Item is changed to the list.
/// </summary>
/// <param name="sender"></param>
/// <param name="e">ItemEventArgs</param>
protected virtual void OnItemChanged(object sender, ItemEventArgs<T> e)
{
if (ItemChanged != null)
{
ItemChanged(sender, e);
}
}
/// <summary>
/// Raised before an Item is removed from the list.
/// </summary>
/// <param name="sender"></param>
/// <param name="e">ItemEventArgs</param>
protected virtual void OnBeforeItemRemoved(object sender, ItemEventArgs<T> e)
{
if (BeforeItemRemoved != null)
{
BeforeItemRemoved(sender, e);
}
}
/// <summary>
/// Raised when an Item is removed from the list.
/// </summary>
/// <param name="sender">object</param>
/// <param name="e">ItemEventsArgs</param>
protected virtual void OnItemRemoved(object sender, ItemEventArgs<T> e)
{
if (ItemRemoved != null)
{
ItemRemoved(sender, e);
}
}
/// <summary>
/// Raised when the Items are cleared from this list.
/// </summary>
/// <param name="sender">object</param>
/// <param name="e">EventArgs</param>
protected virtual void OnItemsCleared(object sender, EventArgs e)
{
if (ItemsCleared != null)
{
ItemsCleared(sender, e);
}
}
#endregion
}
public class ItemEventArgs<T> : EventArgs
{
/// <summary>
/// Item
/// </summary>
public T Item { get; private set; }
/// <summary>
/// Default constructor
/// </summary>
/// <param name="Item"></param>
public ItemEventArgs(T Item)
{
this.Item = Item;
}
}
public class ItemsEventArgs<T> : EventArgs
{
/// <summary>
/// Items
/// </summary>
public T[] Items { get; private set; }
/// <summary>
/// Default constructor
/// </summary>
/// <param name="Items"></param>
public ItemsEventArgs(T[] Items)
{
this.Items = Items;
}
}
}
I might be mistaken. But you could do it this way and your inheritance problem would not be present. I'll try to give a simple example :
You collection class could be of this kind :
public class MyCollection
{
IList<string> MyList { get; set; }
public event EventHandler<StringEventArgs> OnAdded;
public event EventHandler<StringEventArgs> OnRemoved;
public MyCollection()
{
MyList = new List<string>();
}
public void Add(string s)
{
MyList.Add(s);
if (OnAdded != null)
OnAdded(this, new StringEventArgs() { StringAddedOrRemoved = s });
}
public void Remove(string s)
{
MyList.Remove(s);
if (OnRemoved != null)
OnRemoved(this, new StringEventArgs() { StringAddedOrRemoved = s });
}
}
Really simple class with two customized EventHandlers :
public class StringEventArgs : EventArgs
{
public string StringAddedOrRemoved;
public override string ToString()
{
return StringAddedOrRemoved;
}
}
Nothing hard to understand here and then based on the three forms you could use your forms this way.
The first one holds two buttons to interact with the collection and creates the two forms which will observe your collection :
public partial class Form1 : Form
{
public static MyCollection collection;
public Form1()
{
InitializeComponent();
collection = new MyCollection();
Form2 form2 = new Form2();
form2.Show();
Form3 form3 = new Form3();
form3.Show();
collection.OnAdded += form2.MyCollectionAdded;
collection.OnRemoved += form2.MyCollectionRemoved;
collection.OnAdded += form3.MyCollectionAdded;
collection.OnRemoved += form3.MyCollectionRemoved;
}
private void Add_Click(object sender, EventArgs e)
{
collection.Add("test add");
}
private void button1_Click(object sender, EventArgs e)
{
collection.Remove("test add");
}
}
The collection gets linked to each of the functions of the forms that will be observed here :
collection.OnAdded += form2.MyCollectionAdded;
collection.OnRemoved += form2.MyCollectionRemoved;
collection.OnAdded += form3.MyCollectionAdded;
collection.OnRemoved += form3.MyCollectionRemoved;
And so we need to implement those forms :
public partial class Form2 : Form
{
public string Name { get; set; }
public bool Flag { get; set; }
public Form2()
{
InitializeComponent();
}
public void MyCollectionAdded(object sender, StringEventArgs e)
{
//Some action
Flag = true;
label1.Text = string.Format("{0} has added {1} to its list, flag={2}", Name, e.StringAddedOrRemoved, Flag);
}
public void MyCollectionRemoved(object sender, StringEventArgs e)
{
//Some action
Flag = false;
label1.Text = string.Format("{0} has removed {1} from its list, flag={2}", Name, e.StringAddedOrRemoved, Flag);
}
}
I am inheriting my stuff from Form but it could be inherited form whatever you want actually. If you want to share some code among different forms, think of helper functions in a static class, or of whatever pattern that might suit your need.
Hope it helps a bit, and that I am not completely out of scope!
[EDIT] Oops didn't see the Edit, sorry pal![/EDIT]
Which version of .net ,you are using if it is >= 3.5 , you can make use of ObservableCollection to achive what ever you are doing
There is an 'ObservableCollection' in the Framework just for this type of thing. See here.

Problem when extending asp:Repeater with DataPager

I'm extending asp:Repeater to use DataPager, and now my code work with SqlDataSource. To get better performance, I want to use ObjectDataSource with it, but I have to use QueryStringField of DataPager, otherwise I have to click page number twice to make it work. Can any one help on this? this is my code:
namespace WebTest.UserControl
{
public class PageableRepeater : Repeater, IPageableItemContainer
{
private static readonly object EventTotalRowCountAvailable = new object();
private int _startRowIndex = 0;
private int _maximumRows = -1;
private int _totalRowCount = -1;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Page.RegisterRequiresControlState(this);
}
protected override void LoadControlState(object savedState)
{
_startRowIndex = 0;
_maximumRows = -1;
_totalRowCount = -1;
object[] state = savedState as object[];
if (state != null)
{
base.LoadControlState(state[0]);
if (state[1] != null)
{
_totalRowCount = (int)state[1];
}
}
else
{
base.LoadControlState(null);
}
if (!IsViewStateEnabled)
{
OnTotalRowCountAvailable(new PageEventArgs(_startRowIndex, _maximumRows, _totalRowCount));
}
}
protected override object SaveControlState()
{
object baseState = base.SaveControlState();
if (baseState != null || _totalRowCount != -1)
{
object[] state = new object[2];
state[0] = baseState;
state[1] = _totalRowCount;
return state;
}
return true;
}
protected override System.Collections.IEnumerable GetData()
{
ListViewPagedDataSource pagedDataSource = new ListViewPagedDataSource();
pagedDataSource.StartRowIndex = _startRowIndex;
pagedDataSource.MaximumRows = _maximumRows;
if (DataSource is ObjectDataSource)
{
SelectArguments.StartRowIndex = _startRowIndex;
SelectArguments.MaximumRows = _maximumRows;
SelectArguments.RetrieveTotalRowCount = true;
pagedDataSource.DataSource = base.GetData();
_totalRowCount = SelectArguments.TotalRowCount;
pagedDataSource.AllowServerPaging = true;
pagedDataSource.TotalRowCount = _totalRowCount;
}
else
{
pagedDataSource.DataSource = base.GetData();
pagedDataSource.AllowServerPaging = false;
pagedDataSource.TotalRowCount = 0;
_totalRowCount = pagedDataSource.DataSourceCount;
}
return pagedDataSource;
}
protected override void CreateControlHierarchy(bool useDataSource)
{
base.CreateControlHierarchy(useDataSource);
OnTotalRowCountAvailable(new PageEventArgs(_startRowIndex, _maximumRows, _totalRowCount));
}
private void OnTotalRowCountAvailable(PageEventArgs pageEventArgs)
{
EventHandler<PageEventArgs> handler = (EventHandler<PageEventArgs>)Events[EventTotalRowCountAvailable];
if (handler != null)
{
handler(this, pageEventArgs);
}
}
public int MaximumRows
{
get { return _maximumRows; }
}
public int StartRowIndex
{
get { return _startRowIndex; }
}
public void SetPageProperties(int startRowIndex, int maximumRows, bool databind)
{
if (maximumRows < 1)
{
throw new ArgumentOutOfRangeException("maximumRows");
}
if (startRowIndex < 0)
{
throw new ArgumentOutOfRangeException("startRowIndex");
}
_startRowIndex = startRowIndex;
_maximumRows = maximumRows;
if (databind)
{
RequiresDataBinding = true;
}
}
public event EventHandler<PageEventArgs> TotalRowCountAvailable
{
add
{
Events.AddHandler(EventTotalRowCountAvailable, value);
}
remove
{
Events.RemoveHandler(EventTotalRowCountAvailable, value);
}
}
}
}
By the way, I found another implementation to this on CodeProject, but I don't think it use IPageableItemContainer very well.
I know this is an old one, but I've recently been looking for a solution to using the Repeater with a DataPager control.
Most research takes me to this CodeProject article, but it seems like a bit of a hack to me. I've worked on this problem a bit, and put it to the side for a while as I was spinning my wheels on it, until I saw your question and sample code. I was able to take your code and apply it to mine to get a working solution (at least it works for me). With the DataPagerRepeater control below, I'm able to drop the DataPagerRepeater, DataPager, and a DataSource (ObjectDataSource, etc) on the page. Set the DataPagerRepeaters DataSource or DataSourceID to point to the data source, then set the DataPagers PagedControlID to the DataPagerRepeater. Seems to work great.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace My.Web.UI.WebControls
{
/// <summary>
/// Extends the Repeater to be compatable with a DataPager
/// </summary>
/// <remarks>
/// To page through data in a control that implements the IPageableItemContainer interface, DataPager control can be used.
/// Repeater does not support paging and does not implement IPageableItemContainer interface. ListView is the only control that works with DataPager.
///
/// The DataPager control supports built-in paging user interface (UI). NumericPagerField object enables users to select a page of data by page number.
/// NextPreviousPagerField object enables users to move through pages of data one page at a time, or to jump to the first or last page of data.
/// The size of the pages of data is set by using the PageSize property of the DataPager control. One or more pager field objects can be used in
/// a single DataPager control. Custom paging UI can be created by using the TemplatePagerField object. In the TemplatePagerField template,
/// the DataPager control is referenced by using the Container property which provides access to the properties of the DataPager control.
/// These properties include the starting row index, the page size, and the total number of rows currently bound to the control.
/// </remarks>
[ToolboxData("<my:DataPagerRepeater runat=server></my:DataPagerRepeater>")]
[Themeable(true)]
public class DataPagerRepeater : Repeater, IPageableItemContainer
{
/// <summary>Gets the maximum number of items to display on a single page of the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control.
/// </summary>
/// <returns>The maximum number of items to display on a single page of the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control.
/// </returns>
public int MaximumRows
{
get;
//{
// return ViewState["maxrows"] != null ? (int)ViewState["maxrows"] : -1;
//}
private set;
//{
// ViewState["maxrows"] = value;
//}
}
/// <summary>Gets the index of the first record that is displayed on a page of data in the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control.
/// </summary>
/// <returns>The index of the first record that is displayed on a page of data in the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control.
/// </returns>
public int StartRowIndex
{
get;
//{
// return ViewState["startrowindex"] != null ? (int)ViewState["startrowindex"] : -1;
//}
private set;
//{
// ViewState["startrowindex"] = value;
//}
}
/// <summary>
/// Total number of rows that are avialable, regardless of what is currently being displayed
/// </summary>
private int TotalRowsAvailable
{
get;
//{
// return ViewState["totalrows"] != null ? (int)ViewState["totalrows"] : -1;
//}
set;
//{
// ViewState["totalrows"] = value;
//}
}
private static readonly object EventPagePropertiesChanged = new object();
/// <summary>Occurs when the page properties change, after the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control sets the new values.
/// </summary>
public event EventHandler PagePropertiesChanged
{
add
{
base.Events.AddHandler(DataPagerRepeater.EventPagePropertiesChanged, value);
}
remove
{
base.Events.RemoveHandler(DataPagerRepeater.EventPagePropertiesChanged, value);
}
}
private static readonly object EventPagePropertiesChanging = new object();
/// <summary>Occurs when the page properties change, but before the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control sets the new values.
/// </summary>
public event EventHandler<PagePropertiesChangingEventArgs> PagePropertiesChanging
{
add
{
base.Events.AddHandler(DataPagerRepeater.EventPagePropertiesChanging, value);
}
remove
{
base.Events.RemoveHandler(DataPagerRepeater.EventPagePropertiesChanging, value);
}
}
private static readonly object EventTotalRowCountAvailable = new object();
/// <summary>For a description of this member, see <see cref="E:System.Web.UI.WebControls.IPageableItemContainer.TotalRowCountAvailable" />.
/// </summary>
public event EventHandler<PageEventArgs> TotalRowCountAvailable
{
add
{
base.Events.AddHandler(DataPagerRepeater.EventTotalRowCountAvailable, value);
}
remove
{
base.Events.RemoveHandler(DataPagerRepeater.EventTotalRowCountAvailable, value);
}
}
/// <summary>
/// Register the control as one who's control state needs to be persisted
/// </summary>
/// <param name="e"></param>
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Page.RegisterRequiresControlState(this);
}
/// <summary>
/// Initialize the start row index, maximum rows, and total rows available values. Load the total rows available from viewstate.
/// </summary>
/// <param name="savedState"></param>
protected override void LoadControlState(object savedState)
{
this.StartRowIndex = 0;
this.MaximumRows = -1;
this.TotalRowsAvailable = -1;
object[] state = savedState as object[];
if (state != null)
{
base.LoadControlState(state[0]);
if (state[1] != null)
{
this.TotalRowsAvailable = (int)state[1];
}
}
else
{
base.LoadControlState(null);
}
if (!IsViewStateEnabled)
{
OnTotalRowCountAvailable(new PageEventArgs(this.StartRowIndex, this.MaximumRows, this.TotalRowsAvailable));
}
}
/// <summary>
/// Save the total rows available value to viewstate
/// </summary>
/// <returns></returns>
protected override object SaveControlState()
{
object baseState = base.SaveControlState();
if (baseState != null || this.TotalRowsAvailable != -1)
{
object[] state = new object[2];
state[0] = baseState;
state[1] = this.TotalRowsAvailable;
return state;
}
return true;
}
/// <summary>Sets the properties of a page of data in the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control.
/// </summary>
/// <param name="startRowIndex">The index of the first record on the page.</param>
/// <param name="maximumRows">The maximum number of items on a single page.</param>
/// <param name="databind">true to rebind the control after the properties are set; otherwise, false.</param>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <paramref name="maximumRows" /> is less than 1.-or-<paramref name="startRowIndex" /> is less than 0.
/// </exception>
public void SetPageProperties(int startRowIndex, int maximumRows, bool databind)
{
if (maximumRows < 1)
{
throw new ArgumentOutOfRangeException("maximumRows");
}
if (startRowIndex < 0)
{
throw new ArgumentOutOfRangeException("startRowIndex");
}
if (this.StartRowIndex != startRowIndex || this.StartRowIndex != maximumRows)
{
PagePropertiesChangingEventArgs pagePropertiesChangingEventArgs = new PagePropertiesChangingEventArgs(startRowIndex, maximumRows);
if (databind)
{
this.OnPagePropertiesChanging(pagePropertiesChangingEventArgs);
}
this.StartRowIndex = pagePropertiesChangingEventArgs.StartRowIndex;
this.MaximumRows = pagePropertiesChangingEventArgs.MaximumRows;
if (databind)
{
this.OnPagePropertiesChanged(EventArgs.Empty);
}
}
if (databind)
{
this.RequiresDataBinding = true;
}
//this.OnTotalRowCountAvailable(new PageEventArgs(this.StartRowIndex, this.MaximumRows, this.TotalRowsAvailable));
}
/// <summary>
/// Creates a control hierarchy, with or without the specified data source.
/// </summary>
/// <param name="useDataSource">
/// Indicates whether to use the specified data source.
/// </param>
protected override void CreateControlHierarchy(bool useDataSource)
{
base.CreateControlHierarchy(useDataSource);
OnTotalRowCountAvailable(new PageEventArgs(this.StartRowIndex, this.MaximumRows, this.TotalRowsAvailable));
}
/// <summary>Returns an <see cref="T:System.Collections.IEnumerable" /> interface from the data source.</summary>
/// <returns>An object implementing <see cref="T:System.Collections.IEnumerable" /> that represents the data from the data source.</returns>
protected override System.Collections.IEnumerable GetData()
{
System.Collections.IEnumerable data = base.GetData();
this.TotalRowsAvailable = this.SelectArguments.TotalRowCount;
this.OnTotalRowCountAvailable(new PageEventArgs(this.StartRowIndex, this.MaximumRows, this.TotalRowsAvailable));
return data;
}
/// <summary>Raises the <see cref="E:InteriorHealth.Web.UI.WebControls.DataPagerRepeater.PagePropertiesChanging" /> event.
/// </summary>
/// <param name="e">The event data.</param>
protected virtual void OnPagePropertiesChanging(PagePropertiesChangingEventArgs e)
{
EventHandler<PagePropertiesChangingEventArgs> eventHandler = (EventHandler<PagePropertiesChangingEventArgs>)base.Events[DataPagerRepeater.EventPagePropertiesChanging];
if (eventHandler != null)
{
eventHandler(this, e);
}
}
/// <summary>Raises the <see cref="E:InteriorHealth.Web.UI.WebControls.DataPagerRepeater.SelectedIndexChanged" /> event.</summary>
/// <param name="e">The event data.</param>
protected virtual void OnPagePropertiesChanged(EventArgs e)
{
EventHandler eventHandler = (EventHandler)base.Events[DataPagerRepeater.EventPagePropertiesChanged];
if (eventHandler != null)
{
eventHandler(this, e);
}
}
/// <summary>Raises the <see cref="E:InteriorHealth.Web.UI.WebControls.DataPagerRepeater.PagePropertiesChanging" /> event.</summary>
/// <param name="e">The event data.</param>
protected virtual void OnTotalRowCountAvailable(PageEventArgs e)
{
EventHandler<PageEventArgs> eventHandler = (EventHandler<PageEventArgs>)base.Events[DataPagerRepeater.EventTotalRowCountAvailable];
if (eventHandler != null)
{
eventHandler(this, e);
}
}
/// <summary>
/// Override the selection of rows that we need
/// </summary>
/// <returns></returns>
protected override DataSourceSelectArguments CreateDataSourceSelectArguments()
{
DataSourceSelectArguments arg = base.CreateDataSourceSelectArguments();
arg.StartRowIndex = this.StartRowIndex;
arg.MaximumRows = this.MaximumRows;
return arg;
}
}
}

Categories

Resources