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.
Related
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; } }
}
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);
I want to know what how to avoid or stop FileSystemWatcher raise event twice in C#? I have a solution that will detect everytime if there is newly created xml file from a folder. I test my application using creating xml file using notepad but from the listbox it displays twice.
How can I fix this issue?
Here is my code:
private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
{
try
{
fileSystemWatcher1.EnableRaisingEvents = false;
listBox1.Items.Add(e.FullPath);
}
finally
{
fileSystemWatcher1.EnableRaisingEvents = true;
}
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult dialogSelectFolder = folderBrowserDialog1.ShowDialog();
if (dialogSelectFolder.ToString() == "OK")
{
textBox1.Text = folderBrowserDialog1.SelectedPath;
button2.Enabled = true;
}
}
private void button2_Click(object sender, EventArgs e)
{
button1.Enabled = false;
button2.Enabled = false;
button3.Enabled = true;
fileSystemWatcher1.EnableRaisingEvents = true;
fileSystemWatcher1.Path = textBox1.Text;
fileSystemWatcher1.Filter = "*.xml";
}
private void button3_Click(object sender, EventArgs e)
{
button1.Enabled = true;
button3.Enabled = false;
textBox1.Text = "";
fileSystemWatcher1.EnableRaisingEvents = false;
}
}
I have stumbled upon this problem myself twice and i created a class that helps you get only one event at a time. You might also get false events when the file is not in read mode (such as when you copy a file).
You have to create a queue and store all events there and if a time interval passes then raise the appropriate event.
Unfortunately this is not a simple function thus i will include complete code.
using System;
using System.IO;
using System.Timers;
using System.Collections;
using System.ComponentModel;
namespace menelabs.core
{
/// <summary>
/// This class wraps FileSystemEventArgs and RenamedEventArgs objects and detection of duplicate events.
/// </summary>
internal class DelayedEvent
{
private readonly FileSystemEventArgs _args;
/// <summary>
/// Only delayed events that are unique will be fired.
/// </summary>
private bool _delayed;
public DelayedEvent(FileSystemEventArgs args)
{
_delayed = false;
_args = args;
}
public FileSystemEventArgs Args
{
get
{
return _args;
}
}
public bool Delayed
{
get
{
return _delayed;
}
set
{
_delayed = value;
}
}
public virtual bool IsDuplicate(object obj)
{
DelayedEvent delayedEvent = obj as DelayedEvent;
if (delayedEvent == null)
return false; // this is not null so they are different
FileSystemEventArgs eO1 = _args;
RenamedEventArgs reO1 = _args as RenamedEventArgs;
FileSystemEventArgs eO2 = delayedEvent._args;
RenamedEventArgs reO2 = delayedEvent._args as RenamedEventArgs;
// The events are equal only if they are of the same type (reO1 and reO2
// are both null or NOT NULL) and have all properties equal.
// We also eliminate Changed events that follow recent Created events
// because many apps create new files by creating an empty file and then
// they update the file with the file content.
return ((eO1 != null && eO2 != null && eO1.ChangeType == eO2.ChangeType
&& eO1.FullPath == eO2.FullPath && eO1.Name == eO2.Name) &&
((reO1 == null & reO2 == null) || (reO1 != null && reO2 != null &&
reO1.OldFullPath == reO2.OldFullPath && reO1.OldName == reO2.OldName))) ||
(eO1 != null && eO2 != null && eO1.ChangeType == WatcherChangeTypes.Created
&& eO2.ChangeType == WatcherChangeTypes.Changed
&& eO1.FullPath == eO2.FullPath && eO1.Name == eO2.Name);
}
}
/// <summary>
/// This class wraps a FileSystemWatcher object. The class is not derived
/// from FileSystemWatcher because most of the FileSystemWatcher methods
/// are not virtual. The class was designed to resemble FileSystemWatcher class
/// as much as possible so that you can use FileSystemSafeWatcher instead
/// of FileSystemWatcher objects.
/// FileSystemSafeWatcher will capture all events from the FileSystemWatcher object.
/// The captured events will be delayed by at least ConsolidationInterval milliseconds in order
/// to be able to eliminate duplicate events. When duplicate events are found, the last event
/// is droped and the first event is fired (the reverse is not recomended because it could
/// cause some events not be fired at all since the last event will become the first event and
/// it won't fire a if a new similar event arrives imediately afterwards).
/// </summary>
internal class FileSystemSafeWatcher
{
private readonly FileSystemWatcher _fileSystemWatcher;
/// <summary>
/// Lock order is _enterThread, _events.SyncRoot
/// </summary>
private readonly object _enterThread = new object(); // Only one timer event is processed at any given moment
private ArrayList _events;
private Timer _serverTimer;
private int _consolidationInterval = 1000; // milliseconds
#region Delegate to FileSystemWatcher
public FileSystemSafeWatcher()
{
_fileSystemWatcher = new FileSystemWatcher();
Initialize();
}
public FileSystemSafeWatcher(string path)
{
_fileSystemWatcher = new FileSystemWatcher(path);
Initialize();
}
public FileSystemSafeWatcher(string path, string filter)
{
_fileSystemWatcher = new FileSystemWatcher(path, filter);
Initialize();
}
/// <summary>
/// Gets or sets a value indicating whether the component is enabled.
/// </summary>
/// <value>true if the component is enabled; otherwise, false. The default is false. If you are using the component on a designer in Visual Studio 2005, the default is true.</value>
public bool EnableRaisingEvents
{
get
{
return _fileSystemWatcher.EnableRaisingEvents;
}
set
{
_fileSystemWatcher.EnableRaisingEvents = value;
if (value)
{
_serverTimer.Start();
}
else
{
_serverTimer.Stop();
_events.Clear();
}
}
}
/// <summary>
/// Gets or sets the filter string, used to determine what files are monitored in a directory.
/// </summary>
/// <value>The filter string. The default is "*.*" (Watches all files.)</value>
public string Filter
{
get
{
return _fileSystemWatcher.Filter;
}
set
{
_fileSystemWatcher.Filter = value;
}
}
/// <summary>
/// Gets or sets a value indicating whether subdirectories within the specified path should be monitored.
/// </summary>
/// <value>true if you want to monitor subdirectories; otherwise, false. The default is false.</value>
public bool IncludeSubdirectories
{
get
{
return _fileSystemWatcher.IncludeSubdirectories;
}
set
{
_fileSystemWatcher.IncludeSubdirectories = value;
}
}
/// <summary>
/// Gets or sets the size of the internal buffer.
/// </summary>
/// <value>The internal buffer size. The default is 8192 (8K).</value>
public int InternalBufferSize
{
get
{
return _fileSystemWatcher.InternalBufferSize;
}
set
{
_fileSystemWatcher.InternalBufferSize = value;
}
}
/// <summary>
/// Gets or sets the type of changes to watch for.
/// </summary>
/// <value>One of the System.IO.NotifyFilters values. The default is the bitwise OR combination of LastWrite, FileName, and DirectoryName.</value>
/// <exception cref="System.ArgumentException">The value is not a valid bitwise OR combination of the System.IO.NotifyFilters values.</exception>
public NotifyFilters NotifyFilter
{
get
{
return _fileSystemWatcher.NotifyFilter;
}
set
{
_fileSystemWatcher.NotifyFilter = value;
}
}
/// <summary>
/// Gets or sets the path of the directory to watch.
/// </summary>
/// <value>The path to monitor. The default is an empty string ("").</value>
/// <exception cref="System.ArgumentException">The specified path contains wildcard characters.-or- The specified path contains invalid path characters.</exception>
public string Path
{
get
{
return _fileSystemWatcher.Path;
}
set
{
_fileSystemWatcher.Path = value;
}
}
/// <summary>
/// Gets or sets the object used to marshal the event handler calls issued as a result of a directory change.
/// </summary>
/// <value>The System.ComponentModel.ISynchronizeInvoke that represents the object used to marshal the event handler calls issued as a result of a directory change. The default is null.</value>
public ISynchronizeInvoke SynchronizingObject
{
get
{
return _fileSystemWatcher.SynchronizingObject;
}
set
{
_fileSystemWatcher.SynchronizingObject = value;
}
}
/// <summary>
/// Occurs when a file or directory in the specified System.IO.FileSystemWatcher.Path is changed.
/// </summary>
public event FileSystemEventHandler Changed;
/// <summary>
/// Occurs when a file or directory in the specified System.IO.FileSystemWatcher.Path is created.
/// </summary>
public event FileSystemEventHandler Created;
/// <summary>
/// Occurs when a file or directory in the specified System.IO.FileSystemWatcher.Path is deleted.
/// </summary>
public event FileSystemEventHandler Deleted;
/// <summary>
/// Occurs when the internal buffer overflows.
/// </summary>
public event ErrorEventHandler Error;
/// <summary>
/// Occurs when a file or directory in the specified System.IO.FileSystemWatcher.Path is renamed.
/// </summary>
public event RenamedEventHandler Renamed;
/// <summary>
/// Begins the initialization of a System.IO.FileSystemWatcher used on a form or used by another component. The initialization occurs at run time.
/// </summary>
public void BeginInit()
{
_fileSystemWatcher.BeginInit();
}
/// <summary>
/// Releases the unmanaged resources used by the System.IO.FileSystemWatcher and optionally releases the managed resources.
/// </summary>
public void Dispose()
{
Uninitialize();
}
/// <summary>
/// Ends the initialization of a System.IO.FileSystemWatcher used on a form or used by another component. The initialization occurs at run time.
/// </summary>
public void EndInit()
{
_fileSystemWatcher.EndInit();
}
/// <summary>
/// Raises the System.IO.FileSystemWatcher.Changed event.
/// </summary>
/// <param name="e">A System.IO.FileSystemEventArgs that contains the event data.</param>
protected void OnChanged(FileSystemEventArgs e)
{
if (Changed != null)
Changed(this, e);
}
/// <summary>
/// Raises the System.IO.FileSystemWatcher.Created event.
/// </summary>
/// <param name="e">A System.IO.FileSystemEventArgs that contains the event data.</param>
protected void OnCreated(FileSystemEventArgs e)
{
if (Created != null)
Created(this, e);
}
/// <summary>
/// Raises the System.IO.FileSystemWatcher.Deleted event.
/// </summary>
/// <param name="e">A System.IO.FileSystemEventArgs that contains the event data.</param>
protected void OnDeleted(FileSystemEventArgs e)
{
if (Deleted != null)
Deleted(this, e);
}
/// <summary>
/// Raises the System.IO.FileSystemWatcher.Error event.
/// </summary>
/// <param name="e">An System.IO.ErrorEventArgs that contains the event data.</param>
protected void OnError(ErrorEventArgs e)
{
if (Error != null)
Error(this, e);
}
/// <summary>
/// Raises the System.IO.FileSystemWatcher.Renamed event.
/// </summary>
/// <param name="e">A System.IO.RenamedEventArgs that contains the event data.</param>
protected void OnRenamed(RenamedEventArgs e)
{
if (Renamed != null)
Renamed(this, e);
}
/// <summary>
/// A synchronous method that returns a structure that contains specific information on the change that occurred, given the type of change you want to monitor.
/// </summary>
/// <param name="changeType">The System.IO.WatcherChangeTypes to watch for.</param>
/// <returns>A System.IO.WaitForChangedResult that contains specific information on the change that occurred.</returns>
public WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType)
{
//TODO
throw new NotImplementedException();
}
/// <summary>
/// A synchronous method that returns a structure that contains specific information on the change that occurred, given the type of change you want to monitor
/// and the time (in milliseconds) to wait before timing out.
/// </summary>
/// <param name="changeType">The System.IO.WatcherChangeTypes to watch for.</param>
/// <param name="timeout">The time (in milliseconds) to wait before timing out.</param>
/// <returns>A System.IO.WaitForChangedResult that contains specific information on the change that occurred.</returns>
public WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType, int timeout)
{
//TODO
throw new NotImplementedException();
}
#endregion
#region Implementation
private void Initialize()
{
_events = ArrayList.Synchronized(new ArrayList(32));
_fileSystemWatcher.Changed += new FileSystemEventHandler(this.FileSystemEventHandler);
_fileSystemWatcher.Created += new FileSystemEventHandler(this.FileSystemEventHandler);
_fileSystemWatcher.Deleted += new FileSystemEventHandler(this.FileSystemEventHandler);
_fileSystemWatcher.Error += new ErrorEventHandler(this.ErrorEventHandler);
_fileSystemWatcher.Renamed += new RenamedEventHandler(this.RenamedEventHandler);
_serverTimer = new Timer(_consolidationInterval);
_serverTimer.Elapsed += new ElapsedEventHandler(this.ElapsedEventHandler);
_serverTimer.AutoReset = true;
_serverTimer.Enabled = _fileSystemWatcher.EnableRaisingEvents;
}
private void Uninitialize()
{
if (_fileSystemWatcher != null)
_fileSystemWatcher.Dispose();
if (_serverTimer != null)
_serverTimer.Dispose();
}
private void FileSystemEventHandler(object sender, FileSystemEventArgs e)
{
_events.Add(new DelayedEvent(e));
}
private void ErrorEventHandler(object sender, ErrorEventArgs e)
{
OnError(e);
}
private void RenamedEventHandler(object sender, RenamedEventArgs e)
{
_events.Add(new DelayedEvent(e));
}
private void ElapsedEventHandler(Object sender, ElapsedEventArgs e)
{
// We don't fire the events inside the lock. We will queue them here until
// the code exits the locks.
Queue eventsToBeFired = null;
if (System.Threading.Monitor.TryEnter(_enterThread))
{
// Only one thread at a time is processing the events
try
{
eventsToBeFired = new Queue(32);
// Lock the collection while processing the events
lock (_events.SyncRoot)
{
DelayedEvent current;
for (int i = 0; i < _events.Count; i++)
{
current = _events[i] as DelayedEvent;
if (current.Delayed)
{
// This event has been delayed already so we can fire it
// We just need to remove any duplicates
for (int j = i + 1; j < _events.Count; j++)
{
if (current.IsDuplicate(_events[j]))
{
// Removing later duplicates
_events.RemoveAt(j);
j--; // Don't skip next event
}
}
bool raiseEvent = true;
if (current.Args.ChangeType == WatcherChangeTypes.Created || current.Args.ChangeType == WatcherChangeTypes.Changed)
{
//check if the file has been completely copied (can be opened for read)
FileStream stream = null;
try
{
stream = File.Open(current.Args.FullPath, FileMode.Open, FileAccess.Read, FileShare.None);
// If this succeeds, the file is finished
}
catch (IOException)
{
raiseEvent = false;
}
finally
{
if (stream != null) stream.Close();
}
}
if (raiseEvent)
{
// Add the event to the list of events to be fired
eventsToBeFired.Enqueue(current);
// Remove it from the current list
_events.RemoveAt(i);
i--; // Don't skip next event
}
}
else
{
// This event was not delayed yet, so we will delay processing
// this event for at least one timer interval
current.Delayed = true;
}
}
}
}
finally
{
System.Threading.Monitor.Exit(_enterThread);
}
}
// else - this timer event was skipped, processing will happen during the next timer event
// Now fire all the events if any events are in eventsToBeFired
RaiseEvents(eventsToBeFired);
}
public int ConsolidationInterval
{
get
{
return _consolidationInterval;
}
set
{
_consolidationInterval = value;
_serverTimer.Interval = value;
}
}
protected void RaiseEvents(Queue deQueue)
{
if ((deQueue != null) && (deQueue.Count > 0))
{
DelayedEvent de;
while (deQueue.Count > 0)
{
de = deQueue.Dequeue() as DelayedEvent;
switch (de.Args.ChangeType)
{
case WatcherChangeTypes.Changed:
OnChanged(de.Args);
break;
case WatcherChangeTypes.Created:
OnCreated(de.Args);
break;
case WatcherChangeTypes.Deleted:
OnDeleted(de.Args);
break;
case WatcherChangeTypes.Renamed:
OnRenamed(de.Args as RenamedEventArgs);
break;
}
}
}
}
#endregion
}
}
You may find the code at:
https://github.com/melenaos/FileSystemSafeWatcher/blob/master/FileSystemSafeWatcher.cs
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.
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;
}
}
}