Some rows are collapsed in DataGrid, I am getting issue in KeyBoard navigation - wpfdatagrid

I am using DataGrid, run time i make visible collapse some rows.
Suppose my 4th row's visibility is collapse, and my focus is on 3rd row, when i try to move on 5th row with the help of Down-Arrow key, it is not working. Same way if my focus on 5th row and want to move on 3rd row with Up-Arrow key, it is also not working.
Now, what should i do?

This is actually a bug in .Net, there is a bug report here.
One workaround is to use Attached behavior to handle the up and down selection. The following example requires the IsSynchronizedWithCurrentItem to be set to true for the DataGrid.
Note! make sure you change the while condition to the appropriate way to determine if the item is collapsed.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;
namespace DataGridGroupingTest
{
class DataGridKeyboardNavigationAttachedBehavior
{
public static readonly DependencyProperty
KeyboardKey
= DependencyProperty.RegisterAttached(
"IsKeyboardNavigationEnabled",
typeof(bool),
typeof(DataGridKeyboardNavigationAttachedBehavior),
new PropertyMetadata(
false,
OnIsKeyboardNavigationEnabledChanged));
public static bool GetIsKeyboardNavigationEnabled(DependencyObject depObj)
{
return (bool)depObj.GetValue(KeyboardKey);
}
public static void SetIsKeyboardNavigationEnabled(DependencyObject depObj, bool value)
{
depObj.SetValue(KeyboardKey, value);
}
private static void OnIsKeyboardNavigationEnabledChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
DataGrid dataGrid = depObj as DataGrid;
if (dataGrid != null)
{
dataGrid.PreviewKeyDown += dataGrid_PreviewKeyDown;
dataGrid.IsSynchronizedWithCurrentItem = true;
}
}
static void dataGrid_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
DataGrid dataGrid = sender as DataGrid;
if (dataGrid != null && dataGrid.CurrentCell != null)
{
if (e.Key == System.Windows.Input.Key.Down || e.Key == System.Windows.Input.Key.Up)
{
ICollectionView view = CollectionViewSource.GetDefaultView(dataGrid.Items);
int loopCount = 0;
do
{
if (e.Key == System.Windows.Input.Key.Down)
{
view.MoveCurrentToNext();
if (view.IsCurrentAfterLast)
{
view.MoveCurrentToFirst();
loopCount++;
}
}
if (e.Key == System.Windows.Input.Key.Up)
{
view.MoveCurrentToPrevious();
if (view.IsCurrentBeforeFirst)
{
view.MoveCurrentToLast();
loopCount++;
}
}
} while (((Person)view.CurrentItem).Boss != null && !((Person)view.CurrentItem).Boss.IsExpanded && loopCount < 2);
// We have to move the cell selection aswell.
dataGrid.CurrentCell = new DataGridCellInfo(view.CurrentItem, dataGrid.CurrentCell.Column);
e.Handled = true;
return;
}
}
}
}
}

Related

Save and displaying high score with variable across classes unity

I need to get the variable score from my other class and set it as a UserPrefs key. it doesnt seem to be setting as i have a GUI label ingame which shos "None" if there is no UserPrefs key "Highscore".
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
public class Player : MonoBehaviour {
public Vector2 jumpForce = new Vector2(0, 300);
private Rigidbody2D rb2d;
Generator SwagScript;
GameObject generator;
// Use this for initialization
void Start () {
rb2d = gameObject.GetComponent<Rigidbody2D>();
generator = GameObject.FindGameObjectWithTag("Generator");
SwagScript = generator.GetComponent<Generator>();
}
// Update is called once per frame
void Update () {
if (Input.GetKeyUp("space"))
{
rb2d.velocity = Vector2.zero;
rb2d.AddForce(jumpForce);
}
Vector2 screenPosition = Camera.main.WorldToScreenPoint(transform.position);
if (screenPosition.y > Screen.height || screenPosition.y < 0)
{
Die();
}
}
void OnCollisionEnter2D(Collision2D other)
{
Die();
}
void Die()
{
if (PlayerPrefs.HasKey("HighScore"))
{
if (PlayerPrefs.GetInt("Highscore") < SwagScript.score)
{
PlayerPrefs.SetInt("HighScore", SwagScript.score);
}
else
{
PlayerPrefs.SetInt("HighScore", SwagScript.score);
}
}
Application.LoadLevel(Application.loadedLevel);
}
}
Unless you're creating the Highscore playerpref somewhere else, the Die() method won't never create it, since the if (PlayerPrefs.HasKey("HighScore")) will always return false.
Just remove that if.

How to display a Labels 'Error on ErrorProvider1'

Goal
I want to display the text that I put in the Label's "Error on ErrorProvider1" attribute whenever I get an error. See the following label's attributes below.
I try to display the text in the red rectangle into my ErrorProvider1 SetError(control, value) function.
If TextBox1.Text.Trim.Contains("'") Then
ErrorProvider1.SetError(lblErr, ErrorProvider1.GetError(lblErr))
Else
ErrorProvider1.SetError(lblErr, "")
End If
How can I retrieve the 'Error on ErrorProvider1' text from the lblErr to display it in the ErrorProvider1 SetError value?
The ErrorProvider component is very awkward to use effectively. It is fixable however, I'll give an example in C# that extends the component with some new capabilities:
ShowError(Control ctl, bool enable) displays the text that you entered at design-time when the enable argument is true. The easier-to-use version of SetError().
HasErrors returns true if the any active warning icons are displayed. Handy in your OK button's Click event handler.
FocusError() sets the focus to the first control that has a warning icon, if any. It returns false if no warnings are remaining.
SetError() is a replacement of ErrorProvider.SetError(). You only need it if you add any controls after the form's Load event fired or if you need to modify the warning text.
Add a new class to your project and paste the code shown below. Compile. Drop it from the top of the toolbox onto the form. The design-time behavior is identical. Modestly tested.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.ComponentModel.Design;
class MyErrorProvider : ErrorProvider {
public void ShowError(Control ctl, bool enable) {
// Easy to use version of SetError(), uses design-time text
if (!enable) base.SetError(ctl, "");
else {
if (errors.ContainsKey(ctl)) base.SetError(ctl, errors[ctl]);
else base.SetError(ctl, "No error text available");
}
}
public bool HasErrors {
// True if any errors are present
get {
foreach (var err in errors)
if (!string.IsNullOrEmpty(base.GetError(err.Key))) return true;
return false;
}
}
public bool FocusError() {
// Set the focus to the first control with an active error
foreach (var err in errors) {
if (!string.IsNullOrEmpty(base.GetError(err.Key))) {
err.Key.Focus();
return true;
}
}
return false;
}
public new void SetError(Control ctl, string text) {
// Use this only to add/modify error text after the form's Load event
if (!string.IsNullOrEmpty(text)) {
if (errors.ContainsKey(ctl)) errors[ctl] = text;
else errors.Add(ctl, text);
}
base.SetError(ctl, text);
}
private void initialize(object sender, EventArgs e) {
// Preserve error text
copyErrors(((Form)sender).Controls);
}
private void copyErrors(Control.ControlCollection ctls) {
foreach (Control ctl in ctls) {
var text = this.GetError(ctl);
if (!string.IsNullOrEmpty(text)) {
errors.Add(ctl, text);
base.SetError(ctl, "");
}
copyErrors(ctl.Controls);
}
}
private Dictionary<Control, string> errors = new Dictionary<Control, string>();
// Plumbing to hook the form's Load event
[Browsable(false)]
public new ContainerControl ContainerControl {
get { return base.ContainerControl; }
set {
if (base.ContainerControl == null) {
var form = value.FindForm();
if (form != null) form.Load += initialize;
}
base.ContainerControl = value;
}
}
public override ISite Site {
set {
// Runs at design time, ensures designer initializes ContainerControl
base.Site = value;
if (value == null) return;
IDesignerHost service = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (service == null) return;
IComponent rootComponent = service.RootComponent;
this.ContainerControl = rootComponent as ContainerControl;
}
}
}
Your issue is that you are replacing the error message when nothing is wrong. As noted in your comment below, you are storing the localized error message in the label's Tag, so you can do the following:
If TextBox1.Text.Trim.Contains("'") Then
ErrorProvider1.SetError(lblErr, lblErr.Tag)
Else
ErrorProvider1.SetError(lblErr, "")
End If
You were correct to use ErrorProvider1.GetError(Control) to get the value. It's just that you're more than likely replacing it with an empty string before you were retrieving it.

Custom control child controls not persisted to ViewState in ASP.NET 4.0

We just switched target framework in our ASP.NET web application from 3.5 to 4.0. We ran into the following problem:
We have a couple of custom controls that worked fine in 3.5 but now with 4.0 they are not persisted in ViewState, one of them is basically a wrapper for other controls that inherits the Label class and the aspx-code looks like this:
<fsc:FormLabel ID="l_purchaserNo" runat="server" CssClass="label" Text="Purchaser">
<asp:TextBox ID="tb_purchaserNo" runat="server" CssClass="textBox" MaxLength="50" />
</fsc:FormLabel>
and the resulting html is:
<span id="l_purchaserNo" class="label">
<label class="header" for="tb_purchaserNo">Purchaser</label>
<span class="valueContainer">
<input name="tb_purchaserNo" type="text" id="tb_purchaserNo" class="textBox" />
</span>
</span>
So the control basically just adds a few span-tags and a label that is connected to the textbox.
After postback the html-code in 4.0 was:
<span id="l_purchaserNo" class="label"></span>
i.e. everything within the outer wrapper was gone and anything entered in the textbox could not be retreived from code behind.
Below you find the code for our FormLabel class.
We found that by setting ViewStateMode=Disabled on our custom control fsc:FormLabel and ViewStateMode=Enabled on the asp:TextBox the inner controls where persisted to ViewState but at the same time we lost ViewState on the wrapper and since we translate the text on the wrapper label we need viewstate for this as well (actually we tried every combination and setting ViewStateMode=Enabled on fsc:FormLabel did not help, regardless of how we set the ViewStateMode on the page). EnableViewState is true on all levels.
Could someone tell us how to get ViewState to work as before in 3.5, on ALL controls - wrapper as well as wrapped controls?
Thanks
Christian, Zeljko, Jonas
using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace FormLabel
{
public class FormLabel : Label
{
private bool HasChildren
{
get
{
return Controls.Count > 0;
}
}
public override string Text
{
get
{
if (!HasChildren)
{
return base.Text;
}
var text = ViewState[ID + "Text"] as String;
if (text != null)
{
((LiteralControl)Controls[0]).Text = text;
}
return ((LiteralControl)Controls[0]).Text;
}
set
{
if (!HasChildren)
{
base.Text = value;
return;
}
((LiteralControl)Controls[0]).Text = value;
}
}
public void SetText(string text)
{
((LiteralControl)Controls[0]).Text = text;
ViewState[ID + "Text"] = text;
}
public bool IndicateRequired
{
get
{
object state = ViewState[String.Format("{0}_IR", ID)];
return state != null && (bool)state;
}
set
{
ViewState[String.Format("{0}_IR", ID)] = value;
}
}
protected override void OnLoad(EventArgs e)
{
ViewState[ID + "Text"] = Text;
base.OnLoad(e);
}
protected override void Render(HtmlTextWriter writer)
{
if (HasChildren)
{
List<Control> controls = Controls.GetControls();
List<BaseValidator> validators = Controls.GetValidators();
WriteLabelControl(writer);
WriteRequiredIndicator(writer);
WriteControlHeader(writer, validators, this.GetFirstControl());
WriteInnerControls(writer, controls);
WriteLabelEndControl(writer);
return;
}
base.Render(writer);
}
private void WriteLabelControl(HtmlTextWriter writer)
{
writer.WriteBeginTag("span");
writer.WriteAttribute("id", ClientID);
writer.WriteAttribute("class", CssClass);
foreach (string attributeKey in Attributes.Keys)
{
writer.WriteAttribute(attributeKey, Attributes[attributeKey]);
}
writer.Write(HtmlTextWriter.TagRightChar);
}
private void WriteRequiredIndicator(HtmlTextWriter writer)
{
if (IndicateRequired)
{
writer.WriteBeginTag("span");
writer.WriteAttribute("class", "requiredIndicator");
writer.Write(HtmlTextWriter.TagRightChar);
writer.WriteEndTag("span");
}
}
private void WriteControlHeader(HtmlTextWriter writer, IEnumerable<BaseValidator> validators, Control userControl)
{
writer.WriteBeginTag("label");
writer.WriteAttribute("class", "header");
if (userControl != null)
{
writer.WriteAttribute("for", userControl.ClientID);
}
writer.Write(HtmlTextWriter.TagRightChar);
writer.Write(Text);
foreach (BaseValidator validator in validators)
{
validator.CssClass = "Error";
validator.RenderControl(writer);
}
writer.WriteEndTag("label");
}
private static void WriteInnerControls(HtmlTextWriter writer, IList<Control> controls)
{
writer.WriteBeginTag("span");
writer.WriteAttribute("class", "valueContainer");
writer.Write(HtmlTextWriter.TagRightChar);
for (int i = 1; i < controls.Count; i++)
{
controls[i].RenderControl(writer);
}
writer.WriteEndTag("span");
}
private static void WriteLabelEndControl(HtmlTextWriter writer)
{
writer.WriteEndTag("span");
}
}
#region Nested type: Extensions
public static class Extensions
{
public static List<BaseValidator> GetValidators(this ControlCollection controls)
{
var validators = new List<BaseValidator>();
foreach (Control c in controls)
{
if (c is BaseValidator)
{
validators.Add(c as BaseValidator);
}
}
return validators;
}
public static List<Control> GetControls(this ControlCollection controls)
{
var listcontrols = new List<Control>();
foreach (Control c in controls)
{
if (!(c is BaseValidator))
{
listcontrols.Add(c as Control);
}
}
return listcontrols;
}
public static Control GetFirstControl(this Control container)
{
return (new InputControlFinder().FindFirstInputControl(container));
}
private class InputControlFinder
{
public Control FindFirstInputControl(Control control)
{
Control input = null;
foreach (Control child in control.Controls)
{
if (child is TextBox || child is DropDownList || child is CheckBox)
{
input = child;
}
else
{
input = FindFirstInputControl(child);
}
if (input != null)
{
return input;
}
}
return input;
}
}
}
#endregion
}

How do I hide a PivotItem?

I have a Page with an Pivot-control and in some cases I don't want to show a particular PivotItem.
Setting the Visibility to collapsed doesn't seem to affect it at all.
Any suggestions?
you should be able to remove or add PivotItems dynamically in your Pivot by using the respective collection methods on Pivot.Items .
Let me know if this doesn't work for your scenario.
I've created a custom behavior for showing/hiding pivot item
Usage:
< i:Interaction.Behaviors>
< common:HideablePivotItemBehavior Visible="{Binding variable}" />
</ i:Interaction.Behaviors >
Code:
/// <summary>
/// Behavior which enables showing/hiding of a pivot item`
/// </summary>
public class HideablePivotItemBehavior : Behavior<PivotItem>
{
#region Static Fields
public static readonly DependencyProperty VisibleProperty = DependencyProperty.Register(
"Visible",
typeof(bool),
typeof(HideablePivotItemBehavior),
new PropertyMetadata(true, VisiblePropertyChanged));
#endregion
#region Fields
private Pivot _parentPivot;
private PivotItem _pivotItem;
private int _previousPivotItemIndex;
private int _lastPivotItemsCount;
#endregion
#region Public Properties
public bool Visible
{
get
{
return (bool)this.GetValue(VisibleProperty);
}
set
{
this.SetValue(VisibleProperty, value);
}
}
#endregion
#region Methods
protected override void OnAttached()
{
base.OnAttached();
this._pivotItem = AssociatedObject;
}
private static void VisiblePropertyChanged(DependencyObject dpObj, DependencyPropertyChangedEventArgs change)
{
if (change.NewValue.GetType() != typeof(bool) || dpObj.GetType() != typeof(HideablePivotItemBehavior))
{
return;
}
var behavior = (HideablePivotItemBehavior)dpObj;
var pivotItem = behavior._pivotItem;
// Parent pivot has to be assigned after the visual tree is initialized
if (behavior._parentPivot == null)
{
behavior._parentPivot = (Pivot)behavior._pivotItem.Parent;
// if the parent is null return
if (behavior._parentPivot == null)
{
return;
}
}
var parentPivot = behavior._parentPivot;
if (!(bool)change.NewValue)
{
if (parentPivot.Items.Contains(behavior._pivotItem))
{
behavior._previousPivotItemIndex = parentPivot.Items.IndexOf(pivotItem);
parentPivot.Items.Remove(pivotItem);
behavior._lastPivotItemsCount = parentPivot.Items.Count;
}
}
else
{
if (!parentPivot.Items.Contains(pivotItem))
{
if (behavior._lastPivotItemsCount >= parentPivot.Items.Count)
{
parentPivot.Items.Insert(behavior._previousPivotItemIndex, pivotItem);
}
else
{
parentPivot.Items.Add(pivotItem);
}
}
}
}
#endregion
}
You can remove the pivot item from the parent pivot control
parentPivotControl.Items.Remove(pivotItemToBeRemoved);
Removing PivotItems is easy, but if you want to put them back afterwards I've found that the headers get messed up and start overlapping each other. This also happens if you set the Visibility of a header to Collapsed and then later make it Visible again.
So I solved my particular problem by setting the opacity of each unwanted PivotItem (and its header) to 0.
PivotItem p = (PivotItem)MainPivot.Items.ToList()[indexToHide];
p.Opacity = 0;
((UIElement)p.Header).Opacity = 0;
However, this leaves gaps where the missing PivotItems are.
For me, the gaps were not a problem because I only want to remove items at the end of my PivotItemList, so I get some whitespace between the last and first PivotItems. The problem was, I was still able to swipe to a hidden PivotItem. In order to fix this, I overrode Pivot.SelectionChanged() so that whenever the user swipes to a hidden PivotItem, the code moves on to the next item instead. I had to use a DispatchTimer from within SelectionChanged() and actually move to the next PivotItem from the DispatchTimer callback, since you have to be in the UI thread to change PivotItem.SelectedIndex.
private void MainPivot_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
t.Stop(); //t is my DispatchTimer, set to 100ms
if (MainPivot.SelectedIndex >= mFirstHiddenPivotItemIndex)
{
//move to the first or last PivotItem, depending on the current index
if (mCurrentSelectedPivotItemIndex == 0)
mPivotItemToMoveTo = mFirstHiddenPivotItemIndex - 1;
else
mPivotItemToMoveTo = 0;
t.Start();
}
mCurrentSelectedPivotItemIndex = MainPivot.SelectedIndex;
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
MainPivot.SelectedIndex = mPivotItemToMoveTo;
t.Stop();
}
foreach (PivotItem item in MyPivot.Items.ToList())
{
if (item.Visibility == Visibility.Collapsed)
MyPivot.Items.Remove(item);
}
Setting IsLocked property to true will make all other Pivot items to disappear except the current pivot item.
But this will not hide one particular pivot item of our choice.
To elaborate on the solution of adding/removing pivotItems, rather than hiding them.
Let's say we want the pivotItem to be initially invisible, and appear only on a certain event.
mainPivot.Items.Remove(someTab);
Then to add it again,
if (!mainPivot.Items.Cast<PivotItem>().Any(p => p.Name == "someTab"))
{
mainPivot.Items.Insert(1,someTab);
}
I've used Insert rather than add to control the position where the tab appears.
You have to ensure you don't add the same tab twice, which is the reason for the if statement.
I've modified the Bajena behavior to improve it, solving the issue with losing the original position of the PivotItem when showing/hiding repeteadly and the issue when parentpivot control is null (not initialized yet).
Notice that this behavior must be attached to the Pivot, not to the PivotItem.
Code:
public class PivotItemHideableBehavior : Behavior<Pivot>
{
private Dictionary<PivotItem, int> DictionaryIndexes { get; set; }
public static readonly DependencyProperty VisibleProperty = DependencyProperty.Register(
"Visible",
typeof(bool),
typeof(PivotItemHideableBehavior),
new PropertyMetadata(true, VisiblePropertyChanged));
public static readonly DependencyProperty PivotItemProperty = DependencyProperty.Register(
"PivotItem",
typeof(PivotItem),
typeof(PivotItemHideableBehavior),
new PropertyMetadata(null));
public bool Visible
{
get { return (bool)GetValue(VisibleProperty); }
set { SetValue(VisibleProperty, value); }
}
public PivotItem PivotItem
{
get { return (PivotItem)GetValue(PivotItemProperty); }
set { SetValue(PivotItemProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += AssociatedObject_Loaded;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= AssociatedObject_Loaded;
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
DictionaryIndexes = new Dictionary<PivotItem, int>();
int index = 0;
foreach (PivotItem item in AssociatedObject.Items)
DictionaryIndexes.Add(item, index++);
}
private static void VisiblePropertyChanged(DependencyObject dpObj, DependencyPropertyChangedEventArgs change)
{
var behavior = (PivotItemHideableBehavior)dpObj;
var pivot = behavior.AssociatedObject;
if (!behavior.Visible)
{
if (pivot.Items.Contains(behavior.PivotItem))
pivot.Items.Remove(behavior.PivotItem);
}
else if (!pivot.Items.Contains(behavior.PivotItem))
{
int index = 0;
foreach (var item in behavior.DictionaryIndexes)
{
if (item.Key == behavior.PivotItem)
pivot.Items.Insert(index, behavior.PivotItem);
else if (pivot.Items.Contains(item.Key))
index++;
}
}
}
}
Usage:
<Interactivity:Interaction.Behaviors>
<Behaviors:PivotItemHideableBehavior PivotItem="{x:Bind PivotItemName}" Visible="{Binding IsPivotItemVisible}" />
</Interactivity:Interaction.Behaviors>

ReportViewer - modify toolbar?

Do anyone have good ideas of how to modify the toolbar for the WinForms version of the ReportViewer Toolbar?
That is, I want to remove some buttons and varius, but it looks like the solution is to create a brand new toolbar instead of modifying the one that is there.
Like, I had to remove export to excel, and did it this way:
// Disable excel export
foreach (RenderingExtension extension in lr.ListRenderingExtensions()) {
if (extension.Name == "Excel") {
//extension.Visible = false; // Property is readonly...
FieldInfo fi = extension.GetType().GetField("m_isVisible", BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(extension, false);
}
}
A bit trickysh if you ask me..
For removing toolbarbuttons, an possible way was to iterate through the Control array inside the ReportViewer and change the Visible property for the buttons to hide, but it gets reset all the time, so it is not an good way..
WHEN do MS come with an new version btw?
Yeap. You can do that in a little tricky way.
I had a task to add more scale factors to zoom report. I did it this way:
private readonly string[] ZOOM_VALUES = { "25%", "50%", "75%", "100%", "110%", "120%", "125%", "130%", "140%", "150%", "175%", "200%", "300%", "400%", "500%" };
private readonly int DEFAULT_ZOOM = 3;
//--
public ucReportViewer()
{
InitializeComponent();
this.reportViewer1.ProcessingMode = ProcessingMode.Local;
setScaleFactor(ZOOM_VALUES[DEFAULT_ZOOM]);
Control[] tb = reportViewer1.Controls.Find("ReportToolBar", true);
ToolStrip ts;
if (tb != null && tb.Length > 0 && tb[0].Controls.Count > 0 && (ts = tb[0].Controls[0] as ToolStrip) != null)
{
//here we go if our trick works (tested at .NET Framework 2.0.50727 SP1)
ToolStripComboBox tscb = new ToolStripComboBox();
tscb.DropDownStyle = ComboBoxStyle.DropDownList;
tscb.Items.AddRange(ZOOM_VALUES);
tscb.SelectedIndex = 3; //100%
tscb.SelectedIndexChanged += new EventHandler(toolStripZoomPercent_Click);
ts.Items.Add(tscb);
}
else
{
//if there is some problems - just use context menu
ContextMenuStrip cmZoomMenu = new ContextMenuStrip();
for (int i = 0; i < ZOOM_VALUES.Length; i++)
{
ToolStripMenuItem tsmi = new ToolStripMenuItem(ZOOM_VALUES[i]);
tsmi.Checked = (i == DEFAULT_ZOOM);
//tsmi.Tag = (IntPtr)cmZoomMenu;
tsmi.Click += new EventHandler(toolStripZoomPercent_Click);
cmZoomMenu.Items.Add(tsmi);
}
reportViewer1.ContextMenuStrip = cmZoomMenu;
}
}
private bool setScaleFactor(string value)
{
try
{
int percent = Convert.ToInt32(value.TrimEnd('%'));
reportViewer1.ZoomMode = ZoomMode.Percent;
reportViewer1.ZoomPercent = percent;
return true;
}
catch
{
return false;
}
}
private void toolStripZoomPercent_Click(object sender, EventArgs e)
{
ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
ToolStripComboBox tscb = sender as ToolStripComboBox;
if (tscb != null && tscb.SelectedIndex > -1)
{
setScaleFactor(tscb.Items[tscb.SelectedIndex].ToString());
}
else if (tsmi != null)
{
if (setScaleFactor(tsmi.Text))
{
foreach (ToolStripItem tsi in tsmi.Owner.Items)
{
ToolStripMenuItem item = tsi as ToolStripMenuItem;
if (item != null && item.Checked)
{
item.Checked = false;
}
}
tsmi.Checked = true;
}
else
{
tsmi.Checked = false;
}
}
}
Get the toolbar from ReportViewer control:
ToolStrip toolStrip = (ToolStrip)reportViewer.Controls.Find("toolStrip1", true)[0]
Add new items:
toolStrip.Items.Add(...)
There are a lot of properties to set which buttons would you like to see.
For example ShowBackButton, ShowExportButton, ShowFindControls, and so on. Check them in the help, all starts with "Show".
But you are right, you cannot add new buttons. You have to create your own toolbar in order to do this.
What do you mean about new version? There is already a 2008 SP1 version of it.
Another way would be to manipulate the generated HTML at runtime via javascript. It's not very elegant, but it does give you full control over the generated HTML.
For VS2013 web ReportViewer V11 (indicated as rv), the code below adds a button.
private void AddPrintBtn()
{
foreach (Control c in rv.Controls)
{
foreach (Control c1 in c.Controls)
{
foreach (Control c2 in c1.Controls)
{
foreach (Control c3 in c2.Controls)
{
if (c3.ToString() == "Microsoft.Reporting.WebForms.ToolbarControl")
{
foreach (Control c4 in c3.Controls)
{
if (c4.ToString() == "Microsoft.Reporting.WebForms.PageNavigationGroup")
{
var btn = new Button();
btn.Text = "Criteria";
btn.ID = "btnFlip";
btn.OnClientClick = "$('#pnl').toggle();";
c4.Controls.Add(btn);
return;
}
}
}
}
}
}
}
}
I had this question for al ong time I I found the answer after a long tie and the main source of kowledge I used was this webpega: I'd like to thank you all guys adding the code that allowed me to do it and a picture with the result.
Instead of using the ReportViewer Class, you need to create a new classs, in my case, I named it ReportViewerPlus and it goes like this:
using Microsoft.Reporting.WinForms;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace X
{
class ReportViewerPlus : ReportViewer
{
private Button boton { get; set; }
public ReportViewerPlus(Button but) {
this.boton = but;
testc(this.Controls[0]);
}
public ReportViewerPlus()
{
}
private void testc(Control item){
if(item is ToolStrip)
{
ToolStripItemCollection tsic = ((ToolStrip)item).Items;
tsic.Insert(0, new ToolStripControlHost(boton));
return;
}
for (int i = 0; i < item.Controls.Count; i++)
{
testc(item.Controls[i]);
}
}
}
}
You have to add the button directly in the constructor of the class and you can configure the button in your designer.
Here's a pic of the result, not perfect, but enough to go(safe link I swear, but I can't post my own pics, don't have enough reputation).
http://prntscr.com/5lfssj
If you look carefully in the code of the class, you'd see more or less how it works and you could make your changes and make it possible to establish it in other site of the toolbar.
Thank you so much for helping me in the past, I hope this helps lots of people!
Generally you are suppose to create your own toolbar if you want to modify it. Your solution for removing buttons will probably work if that is all you need to do, but if you want to add your own you should probably just bite the bullet and build a replacement.
You may modify reportviewer controls by CustomizeReportToolStrip method.
this example remove Page Setup Button, Page Layout Button in WinForm
public CustOrderReportForm() {
InitializeComponent();
CustomizeReport(this.reportViewer1);
}
private void CustomizeReport(Control reportControl, int recurCount = 0) {
Console.WriteLine("".PadLeft(recurCount + 1, '.') + reportControl.GetType() + ":" + reportControl.Name);
if (reportControl is Button) {
CustomizeReportButton((Button)reportControl, recurCount);
}
else if (reportControl is ToolStrip) {
CustomizeReportToolStrip((ToolStrip)reportControl, recurCount);
}
foreach (Control childControl in reportControl.Controls) {
CustomizeReport(childControl, recurCount + 1);
}
}
//-------------------------------------------------------------
void CustomizeReportToolStrip(ToolStrip c, int recurCount) {
List<ToolStripItem> customized = new List<ToolStripItem>();
foreach (ToolStripItem i in c.Items) {
if (CustomizeReportToolStripItem(i, recurCount + 1)) {
customized.Add(i);
}
}
foreach (var i in customized) c.Items.Remove(i);
}
//-------------------------------------------------------------
void CustomizeReportButton(Button button, int recurCount) {
}
//-------------------------------------------------------------
bool CustomizeReportToolStripItem(ToolStripItem i, int recurCount) {
Console.WriteLine("".PadLeft(recurCount + 1, '.') + i.GetType() + ":" + i.Name);
if (i.Name == "pageSetup") {
return true;
}
else if (i.Name == "printPreview") {
return true;
}
return false; ;
}