RichTextBox with text filtering - c#

How can I implement in richTextBox something like filter (connected e.g. with combobox) that'll be responsible for showing only lines containing selected word (filters)?
I'm not talking about removing other lines - only "hide".
Is it possible?
Eventually I could use another type control, but if it's not neccessary I'd like to use richTextBox.
I thought now, about storing data in some structure, and make filtering based on this used structure. But don't know if it's efficient solution.

Try to make something like this
public string[] RtbFullText;
private void button7_Click(object sender, EventArgs e)
{
RtbFullText = richTextBox1.Text.Split('\n');
}
private void button8_Click(object sender, EventArgs e)
{
//Filter
richTextBox1.Text = "";
foreach (string _s in RtbFullText)
{
if (_s.Contains("Filter"))
richTextBox1.Text += _s + "\n";
}
}

So you can do this
public class NewRichTextBox : RichTextBox
{
public string[] TotalText;
private bool filter = false;
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
if (!filter)
TotalText = Text.Split('\n');
}
public void Filter(string sf)
{
filter = true;
Text = "";
foreach (string _s in TotalText)
{
if (_s.Contains(sf))
Text += _s + "\n";
}
filter = false;
}
}
public Form1()
{
InitializeComponent();
NewRichTextBox myrtb = new NewRichTextBox();
myrtb.Name = "NRTB";
Controls.Add(myrtb);
}
private void button1_Click(object sender, EventArgs e)
{
NewRichTextBox mtrb = (NewRichTextBox)Controls.Find("NRTB", false)[0];
mtrb.Filter("Filter");
}

OMG i do it, use this class:
public class ListWithRTB : IList
{
private List<string> _contents = new List<string>();
private int _count;
string lastsearch = "";
public ListWithRTB()
{
_count = 0;
}
public object rtb;
private void UpdateRtb(string search)
{
lastsearch = search;
if (rtb is RichTextBox)
{
((RichTextBox)rtb).Text = "";
List<string> help_contents;
if (search != "")
help_contents = _contents.Where(s => s.Contains(search)).ToList();
else
help_contents = _contents;
for (int i = 0; i < help_contents.Count; i++)
{
((RichTextBox)rtb).Text += help_contents[i] + "\n";
}
}
}
public void Filter(string search)
{
UpdateRtb(search);
}
public int Add(object value)
{
if (_count < _contents.Count + 1)
{
_contents.Add((string)value);
_count++;
UpdateRtb(lastsearch);
return (_count);
}
else
{
return -1;
}
}
public void RemoveAt(int index)
{
_contents.RemoveAt(index);
_count--;
UpdateRtb(lastsearch);
}
public void Clear()
{
_contents.Clear();
UpdateRtb(lastsearch);
_count = 0;
}
public bool Contains(object value)
{
return _contents.Contains((string)value);
}
public int IndexOf(object value)
{
return _contents.IndexOf((string)value);
}
public void Insert(int index, object value)
{
_contents.Insert(index,(string) value);
_count++;
}
public bool IsFixedSize
{
get
{
return false;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
public void Remove(object value)
{
RemoveAt(IndexOf(value));
}
public object this[int index]
{
get
{
return _contents[index];
}
set
{
_contents[index] = value.ToString();
}
}
public void CopyTo(Array array, int index)
{
int j = index;
for (int i = 0; i < Count; i++)
{
array.SetValue(_contents[i], j);
j++;
}
}
public int Count
{
get
{
return _count;
}
}
public bool IsSynchronized
{
get
{
return false;
}
}
public object SyncRoot
{
get
{
return this;
}
}
public IEnumerator GetEnumerator()
{
throw new Exception("The method or operation is not implemented.");
}
public void PrintContents()
{
Console.WriteLine("List has a capacity of {0} and currently has {1} elements.", _contents.Count, _count);
Console.Write("List contents:");
for (int i = 0; i < Count; i++)
{
Console.Write(" {0}", _contents[i]);
}
Console.WriteLine();
}
}
And this how you can use it
ListWithRTB _mlrtb = new ListWithRTB();
private void button1_Click(object sender, EventArgs e)
{
_mlrtb.rtb = richTextBox1;
_mlrtb.Add("Filter");
_mlrtb.Add("123");
_mlrtb.Add("111 Filter");
}
private void button2_Click(object sender, EventArgs e)
{
_mlrtb.Filter("Filter");
}
private void button3_Click(object sender, EventArgs e)
{
_mlrtb.Filter("");
}

private void Button_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(SearchableString) && !string.IsNullOrEmpty(FullRichtxt))
{
var SplitedTxt = FullRichtxt.Split('\n').ToList<string>();
List<string> filterlist = SplitedTxt.Where(x => x.Contains(contx.SearchableString)).ToList<string>();
string FilterString=string.Empty;
foreach(string str in filterlist)
{
FilterString+=str+"\n";
}
(RichTextBox1 as RichTextBox).AppendText(FilterString);
}
}

I know this has been a very old question however I ran into the same issue and implemented it which also retains any RTF formatting.
/// <summary>
/// This Control allows to filter the content of the RichTextBox by either manually
/// calling <c>ApplyFilter(string)</c> with the search string or specifying a TextBox Control
/// as a filter reference.
///
/// Matching lines will be retained, other will be deleted.
///
/// Retains RTF formatting and when removing the filter restores the original content.
///
/// Ideal for a Debug Console.
///
/// </summary>
public class RichFilterableTextBox : RichTextBox
{
private Timer timer;
private string OriginalRTF = null;
private TextBox _filterReference;
private int _interval = 2000;
public TextBox FilterReference
{
get => _filterReference;
set
{
//if we had already a filter reference
if (_filterReference != null)
{
//we should remove the event
_filterReference.TextChanged -= FilterChanged;
}
_filterReference = value;
//if our new filter reference is not null we need to register our event
if (_filterReference != null)
_filterReference.TextChanged += FilterChanged;
}
}
/// <summary>
/// After the filter has been entered into the FilerReference TextBox
/// this will auto apply the filter once the interval has been passed.
/// </summary>
public int Interval
{
get => _interval;
set
{
_interval = value;
timer.Interval = Interval;
}
}
public RichFilterableTextBox()
{
timer = new Timer();
timer.Interval = Interval;
timer.Tick += TimerIntervalTrigger;
}
public void SetFilterControl(TextBox textbox)
{
this.FilterReference = textbox;
}
public void ApplyFilter(string searchstring)
{
int startIndex = 0;
int offset = 0;
//check each line
foreach (var line in this.Lines)
{
offset = 0;
SelectionStart = startIndex + offset;
SelectionLength = line.Length + 1;
//if our line contains our search string/filter
if (line.Contains(searchstring))
{
//we apply an offset based on the line length
offset = line.Length;
}
else
{
//otherwise delete the line
SelectedText = "";
}
//move the start index forward based on the current selected text
startIndex += this.SelectedText.Length;
}
}
private void FilterChanged(object sender, EventArgs e)
{
//take snapshot of original
if (OriginalRTF == null)
{
OriginalRTF = this.Rtf;
}
else
{
//restore original
Rtf = OriginalRTF;
OriginalRTF = null;
}
timer.Stop();
timer.Start();
}
private void TimerIntervalTrigger(object sender, EventArgs e)
{
//stop the timer to avoid multiple triggers
timer.Stop();
//apply the filter
ApplyFilter(FilterReference.Text);
}
protected override void Dispose(bool disposing)
{
timer.Stop();
timer.Dispose();
base.Dispose(disposing);
}
}
This control can be either used standalone and be filter by calling the method
ApplyFilter(string searchString) with the desired search string. Or it can be connected to a TextBox
where you will be able to enter the phrase in. After a set timer interval it will auto trigger the filtering.
I am using this as a Log Display during runtime where I am also applying color codes to severity and my goal was to retain the formatting as well as be able to quickly search/filter. I attached a few screenshots:
There is still room for improvements and I hope this can be used as a starting code base.

Related

Differentiate items loading to list vs scroll event Xamarin forms listview

This is my code that can successfully detect scroll up or down:
MyListView.ItemAppearing += async (object sender, ItemVisibilityEventArgs e) =>
{
var currentIdx = CurrentList.IndexOf((MyClass)e.Item);
if (currentIdx > _lastItemAppearedIdx)
ShowChopped();
else
ShowFull();
_lastItemAppearedIdx = CurrentList.IndexOf((MyClass)e.Item);
};
What is working is the following: Items get added to the list, then once i start scrolling it works fine where ShowChoppedand ShowFull are methods with animations that just makes a simple animation to either half the size of an object or make it full. This works fine, but if i however click a new category that changes the content in the list, ItemAppearing gets triggered of course and ShowChoppedand ShowFull are called even though i only want it called during a scrollevent.
How would i be able to differentiate a scroll to a item collection change? I have only tried this on iOS.
Updated code:
public class ListView_iOS : ListViewRenderer
{
private IDisposable _offsetObserver;
private double _prevYOffset;
private IListView _myListView;
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
{
base.OnElementChanged(e);
if (e.NewElement is IListView)
_offsetObserver = Control.AddObserver("contentOffset",
Foundation.NSKeyValueObservingOptions.New, HandleAction);
}
private static bool CloseTo(double x, double y)
{
return Math.Abs(x - y) < 0.1;
}
private void HandleAction(Foundation.NSObservedChange obj)
{
var effectiveY = Math.Max(Control.ContentOffset.Y, 0);
if (!CloseTo(effectiveY, _prevYOffset) && Element is IListView)
{
var myList = Element as IListView;
myList.IsScrolling = true;
}
}
}
You can differentiate items loading from list scrolling by
1 adding the code if (EmployeeView.IsScrolling) within ItemAppearing method.
2 adding the code EmployeeView.IsScrolling = false; within any function you write to change the appearing of items without scrolling action, for example, when you add items or change category.
And the EmployeeView.IsScrolling value is set from listview renderer.
So the code is like:
NativeListView.cs
public class NativeListView : ListView
{
public static readonly BindableProperty
IsScrollingProperty =
BindableProperty.Create(nameof(IsScrolling),
typeof(bool), typeof(NativeListView), false);
public bool IsScrolling
{
get { return (bool)GetValue(IsScrollingProperty); }
set { SetValue(IsScrollingProperty, value); }
}
}
NativeAndroidListViewRenderer.cs
[assembly: ExportRenderer(typeof(NativeListView), typeof(NativeAndroidListViewRenderer))]
namespace App2.Droid
{
public class NativeAndroidListViewRenderer : ListViewRenderer
{
public NativeAndroidListViewRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
{
base.OnElementChanged(e);
if (e.NewElement is NativeListView)
Control.Scroll += Control_Scroll;
}
private void Control_Scroll(object sender, AbsListView.ScrollEventArgs e)
{
var myList = Element as NativeListView;
myList.IsScrolling = true;
}
}
}
NativeiOSListViewRenderer.cs
private IDisposable _offsetObserver;
private double _prevYOffset;
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
{
base.OnElementChanged(e);
if (e.NewElement is NativeListView)
_offsetObserver = Control.AddObserver("contentOffset",
Foundation.NSKeyValueObservingOptions.New, HandleAction);
}
private void HandleAction(Foundation.NSObservedChange obj)
{
var effectiveY = Math.Max(Control.ContentOffset.Y, 0);
if (!CloseTo(effectiveY, _prevYOffset) && Element is NativeListView)
{
var myList = Element as NativeListView;
myList.IsScrolling = true;
_prevYOffset = effectiveY;
}
}
private static bool CloseTo(double x, double y)
{
return Math.Abs(x - y) < 0.1;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing && _offsetObserver != null)
{
_offsetObserver.Dispose();
_offsetObserver = null;
}
}
MainPage.xaml.cs
namespace App2
{
public partial class MainPage : ContentPage
{
ObservableCollection<String> employeeList = new ObservableCollection<String>();
int count = 0;
public MainPage()
{
InitializeComponent();
AddButtion.Clicked += AddButtion_Clicked;
DelButtion.Clicked += DelButtion_Clicked;
EmployeeView.ItemsSource = employeeList;
EmployeeView.ItemAppearing += async (object sender, ItemVisibilityEventArgs e) =>
{
if (EmployeeView.IsScrolling) {
await DisplayAlert("ItemAppearing", e.Item + " row is appearing", "OK");
Console.WriteLine("ItemAppearing!!!!!!!!!!");
}
};
}
private void AddButtion_Clicked(object sender, EventArgs e)
{
employeeList.Add("Mr. Mono"+ count++);
EmployeeView.IsScrolling = false;
}
private void DelButtion_Clicked(object sender, EventArgs e)
{
if (employeeList.Count > 0) {
employeeList.RemoveAt(0);
}
EmployeeView.IsScrolling = false;
}
}
}

c# poker checkbox value value dont change

I am doing MVC and I am new at it. I am making a game where 5 dice roll by clicking on the 'roll dice' button and show random numbers. Under each die label there is a check box. If the player clicks on the check box the dice don't roll again and the other dice do roll.
I can show dice numbers in my view but I don't understand how to make it so the dice don't roll if you check the checkbox. I translated my program because it's in dutch: Waarde=value; dobbesteen=dice; werp=throw.
public class Dobbelsteen
{
Random rnd = new Random();
public int Waarde { get; set; }
public bool Checked { get; set; }
public int Worpen { get; set; }
public void Rollen()
{
if (Checked == false)
Waarde = rnd.Next(1, 7);
}
}
public class BusinessController
{
List<int> dice = new List<int>();
Dobbelsteen objdobbelsteen = new Dobbelsteen();
public BusinessController()
{
}
public int Roll()
{
for (int i = 0; i < 5; i++)
{
objdobbelsteen.Rollen();
dice.Add(i);
}
return objdobbelsteen.Waarde;
}
public int Werp()
{
objdobbelsteen.Worpen++;
return objdobbelsteen.Worpen;
}
public int nietroll()
{
int i = 1;
return i;
}
/*public bool Winnaar()
{
if (dice[1] == dice[2])
{
return true;
}
else return false;
}*/
public void SetLock(int p)
{
if(objdobbelsteen.Checked==false)
{
nietroll();
}
}
}
public partial class Form1 : Form
{
BusinessController busniessController = new BusinessController();
public Form1()
{
InitializeComponent();
}
public void Gooien_Click(object sender, EventArgs e)
{
lblWorpen.Text = Convert.ToString(busniessController.Werp());
dblsteen1.Text = Convert.ToString(busniessController.Roll());
dblsteen2.Text = Convert.ToString(busniessController.Roll());
dblsteen3.Text = Convert.ToString(busniessController.Roll());
dblsteen4.Text = Convert.ToString(busniessController.Roll());
dblsteen5.Text = Convert.ToString(busniessController.Roll());
if (dblsteen1.Text==dblsteen2.Text)
MessageBox.Show("u win");
}
public void checkBox1_CheckedChanged(object sender, EventArgs e)
{
busniessController.SetLock(1);
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
busniessController.SetLock(2);
}
private void checkBox3_CheckedChanged(object sender, EventArgs e)
{
busniessController.SetLock(3);
}
private void checkBox4_CheckedChanged(object sender, EventArgs e)
{
busniessController.SetLock(4);
}
private void checkBox5_CheckedChanged(object sender, EventArgs e)
{
busniessController.SetLock(5);
}
}
You need 5 different dices, not just one. In this way each dice can have its own Checked property set to a different value
List<Dobbelsteen> dices = new List<Dobbelsteen>()
{
{new Dobbelsteen()},
{new Dobbelsteen()},
{new Dobbelsteen()},
{new Dobbelsteen()},
{new Dobbelsteen()}
};
public void RollAll()
{
for (int i = 0; i < 5; i++)
dices[i].Rollen();
}
public int GetDiceValue(int i)
{
if(i >= 0 && i <= dices.Count)
return dices[i].Waarde;
else
throw new IndexOutOfRangeException($"Invalid index {i}");
}
public void SetLock(int p)
{
if(p >= 0 && p <= dices.Count)
return dices[p].Checked = true;
else
throw new IndexOutOfRangeException($"Invalid index {p}");
}
Also you should make your Random variable of the class DobbelSteen static otherwise the strict loop inside the Rollen method results in the same value returned for every dice.
After this you can call
busniessController.RollAll();
dblsteen1.Text = busniessController.GetDiceValue(0).ToString();
dblsteen2.Text = busniessController.GetDiceValue(1).ToString();
dblsteen3.Text = busniessController.GetDiceValue(2).ToString();
dblsteen4.Text = busniessController.GetDiceValue(3).ToString();
dblsteen5.Text = busniessController.GetDiceValue(4).ToString();
Finally remember that in NET the index for a collection like a list starts at zero and ends to the collection count - 1. So your call to SetLock should be changed accordingly to avoid the exception
You never actually set the "Checked" value, SetLock refers to the nietRol function which just sets an int. Here you need to set the "Checked" value to true.
And please programmeer niet in het Nederlands maar doe alles in het Engels.

Set tooltip on range of text in wpf richtextbox

I am trying to set a tooltip on an arbitrary range of text on a richtextbox. Is this possible? If so how would I do it e.g by passing in parameters "from" and "to" as (int) indexes.
Thanks
You could use the following as a starting point:
Add a reference to System.Windows.Interactivity.
Add the following classes to your project:
public class TextRangeToolTip
{
public int StartPosition { get; set; }
public int Length { get; set; }
public object ToolTip { get; set; }
internal bool IsInRange(int position)
{
return this.StartPosition <= position && position < this.StartPosition + this.Length;
}
}
public class TextRangeToolTipCollection : ObservableCollection<TextRangeToolTip> {}
[ContentProperty("Ranges")]
public class ToolTipBehavior : Behavior<RichTextBox>
{
private const int ToolTipHideMouseDelta = 9;
public static readonly DependencyProperty RangesProperty
= DependencyProperty.Register("Ranges", typeof(TextRangeToolTipCollection),
typeof (ToolTipBehavior),
new PropertyMetadata(OnRangesChanged));
private readonly DispatcherTimer timer;
private readonly ToolTip toolTip;
private Point lastMousePosition;
public TextRangeToolTipCollection Ranges
{
get
{
return (TextRangeToolTipCollection)this.GetValue(RangesProperty)
?? (this.Ranges = new TextRangeToolTipCollection());
}
set { this.SetValue(RangesProperty, value); }
}
public ToolTipBehavior()
{
this.Ranges = new TextRangeToolTipCollection();
this.timer = new DispatcherTimer();
this.timer.Tick += this.TimerOnTick;
this.timer.Interval = TimeSpan.FromSeconds(1);
this.toolTip = new ToolTip {Placement = PlacementMode.Relative};
}
protected override void OnAttached()
{
this.AssociatedObject.ToolTip = this.toolTip;
this.toolTip.PlacementTarget = this.AssociatedObject;
ToolTipService.SetIsEnabled(this.AssociatedObject, false);
this.AssociatedObject.MouseMove += this.AssociatedObjectOnMouseMove;
}
protected override void OnDetaching()
{
this.timer.Stop();
this.toolTip.PlacementTarget = null;
this.AssociatedObject.ToolTip = null;
this.AssociatedObject.ClearValue(ToolTipService.IsEnabledProperty);
this.AssociatedObject.MouseMove -= this.AssociatedObjectOnMouseMove;
}
private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
{
Point currentMousePosition = mouseEventArgs.GetPosition(this.AssociatedObject);
if (this.AssociatedObject.IsMouseCaptured)
{
Vector delta = currentMousePosition
- this.lastMousePosition;
if (delta.X*delta.X + delta.Y*delta.Y <= ToolTipHideMouseDelta)
{
this.toolTip.HorizontalOffset = currentMousePosition.X + 10;
this.toolTip.VerticalOffset = currentMousePosition.Y + 10;
return;
}
this.AssociatedObject.ReleaseMouseCapture();
this.toolTip.IsOpen = false;
}
if (this.AssociatedObject.IsMouseOver)
{
this.lastMousePosition = currentMousePosition;
this.timer.Stop();
this.timer.Start();
}
}
private static void OnRangesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((ToolTipBehavior) d).OnRangesChanged((IEnumerable<TextRangeToolTip>) e.OldValue,
(IEnumerable<TextRangeToolTip>) e.NewValue);
}
private void OnRangesChanged(IEnumerable<TextRangeToolTip> oldRanges, IEnumerable<TextRangeToolTip> newRanges)
{
var oldObservable = oldRanges as INotifyCollectionChanged;
if (oldObservable != null)
{
CollectionChangedEventManager.RemoveHandler(oldObservable, this.OnRangesCollectionChanged);
}
var newObservable = newRanges as INotifyCollectionChanged;
if (newObservable != null)
{
CollectionChangedEventManager.AddHandler(newObservable, this.OnRangesCollectionChanged);
}
this.UpdateToolTip();
}
private void OnRangesCollectionChanged(
object sender,
NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
{
this.UpdateToolTip();
}
private bool SetToolTipData()
{
if (this.Ranges == null)
{
return false;
}
TextPointer pointer = this.AssociatedObject.GetPositionFromPoint(this.lastMousePosition, false);
if (pointer == null)
{
return false;
}
int position = this.AssociatedObject.Document.ContentStart.GetOffsetToPosition(pointer);
TextRangeToolTip matchingRange = this.Ranges.FirstOrDefault(r => r.IsInRange(position));
if (matchingRange == null)
{
return false;
}
this.toolTip.Content = matchingRange.ToolTip;
return true;
}
private void TimerOnTick(object sender, EventArgs eventArgs)
{
this.timer.Stop();
if (this.AssociatedObject.IsMouseOver && this.SetToolTipData())
{
this.toolTip.IsOpen = true;
this.AssociatedObject.CaptureMouse();
}
}
private void UpdateToolTip()
{
if (this.AssociatedObject != null && this.AssociatedObject.IsMouseCaptured && !this.SetToolTipData())
{
this.toolTip.IsOpen = false;
this.AssociatedObject.ReleaseMouseCapture();
}
}
}
Use it on your RichTextBox like this:
<RichTextBox>
<i:Interaction.Behaviors>
<myapp:ToolTipBehavior>
<myapp:TextRangeToolTip StartPosition="10" Length="4" ToolTip="some" />
<myapp:TextRangeToolTip StartPosition="15" Length="4" ToolTip="text" />
</myapp:ToolTipBehavior>
</i:Interaction.Behaviors>
<FlowDocument>
<Paragraph>This is some text. This is some other text.</Paragraph>
</FlowDocument>
</RichTextBox>
Alternatively, you can bind a TextRangeToolTipCollection to the Ranges property like this:
<RichTextBox Document="{Binding Document}">
<i:Interaction.Behaviors>
<myapp:ToolTipBehavior Ranges="{Binding RangeToolTips}" />
</i:Interaction.Behaviors>
</RichTextBox>
Getting the positions right is a bit tricky, because WPF counts symbols, not characters. You could extend the TextRangeToolTip class to have properties of type TextPointer or TextRange and construct it using your FlowDocument instance.

how to check multiple row in DevExpress CheckEdit

This is my code
gridView1.Columns.Add(new DevExpress.XtraGrid.Columns.GridColumn()
{
Caption = "Selected",
ColumnEdit = new RepositoryItemCheckEdit() { },
VisibleIndex = 1,
UnboundType = DevExpress.Data.UnboundColumnType.Boolean
});
But I cant check multiple checkEdit at the same time.
Why was that?
And please show me the way out.
Thanks.
Well, there are two answers to that question, one very simple, and one very complex, let's start with the simple:
If you want to have an column that has the "Selected" caption and act as a checkbox to indicate that a particular record was selected, you have two options:
1) If you can alter the class in your data source to add a property that is bool and could be used with DataBinding, then, all is done in a very simple way, jast add the property and bind the data and it will work:
class SimplePerson
{
public string Name { get; set; }
public bool IsSelected { get; set; }
}
BindingList<SimplePerson> source = new BindingList<SimplePerson>();
void InitGrid()
{
source.Add(new SimplePerson() { Name = "John", IsSelected = false });
source.Add(new SimplePerson() { Name = "Gabriel", IsSelected = true });
gridControl.DataSource = source;
}
2) You cannot alter you classes, so you need to this by signing the correct grid events and drawing the column yourself, and also adding the right handlers for all the actions.... is a very complex case, but for your luck i have this done, because i have had this problem in the past, so i will post you my full class!
public class GridCheckMarksSelection
{
public event EventHandler SelectionChanged;
protected GridView _view;
protected ArrayList _selection;
private GridColumn _column;
private RepositoryItemCheckEdit _edit;
public GridView View
{
get { return _view; }
set
{
if (_view == value)
return;
if (_view != null)
Detach();
_view = value;
Attach();
}
}
public GridColumn CheckMarkColumn { get { return _column; } }
public int SelectedCount { get { return _selection.Count; } }
public GridCheckMarksSelection()
{
_selection = new ArrayList();
}
public GridCheckMarksSelection(GridView view)
: this()
{
this.View = view;
}
protected virtual void Attach()
{
if (View == null)
return;
_selection.Clear();
_view = View;
_edit = View.GridControl.RepositoryItems.Add("CheckEdit")
as RepositoryItemCheckEdit;
_edit.EditValueChanged += edit_EditValueChanged;
_column = View.Columns.Insert(0);
_column.OptionsColumn.AllowSort = DefaultBoolean.False;
_column.VisibleIndex = int.MinValue;
_column.FieldName = "CheckMarkSelection";
_column.Caption = "Mark";
_column.OptionsColumn.ShowCaption = false;
_column.UnboundType = UnboundColumnType.Boolean;
_column.ColumnEdit = _edit;
View.CustomDrawColumnHeader += View_CustomDrawColumnHeader;
View.CustomDrawGroupRow += View_CustomDrawGroupRow;
View.CustomUnboundColumnData += view_CustomUnboundColumnData;
View.MouseUp += view_MouseUp;
}
protected virtual void Detach()
{
if (_view == null)
return;
if (_column != null)
_column.Dispose();
if (_edit != null)
{
_view.GridControl.RepositoryItems.Remove(_edit);
_edit.Dispose();
}
_view.CustomDrawColumnHeader -= View_CustomDrawColumnHeader;
_view.CustomDrawGroupRow -= View_CustomDrawGroupRow;
_view.CustomUnboundColumnData -= view_CustomUnboundColumnData;
_view.MouseDown -= view_MouseUp;
_view = null;
}
protected virtual void OnSelectionChanged(EventArgs e)
{
if (SelectionChanged != null)
SelectionChanged(this, e);
}
protected void DrawCheckBox(Graphics g, Rectangle r, bool Checked)
{
var info = _edit.CreateViewInfo() as CheckEditViewInfo;
var painter = _edit.CreatePainter() as CheckEditPainter;
ControlGraphicsInfoArgs args;
info.EditValue = Checked;
info.Bounds = r;
info.CalcViewInfo(g);
args = new ControlGraphicsInfoArgs(info, new GraphicsCache(g), r);
painter.Draw(args);
args.Cache.Dispose();
}
private void view_MouseUp(object sender, MouseEventArgs e)
{
if (e.Clicks == 1 && e.Button == MouseButtons.Left)
{
GridHitInfo info;
var pt = _view.GridControl.PointToClient(Control.MousePosition);
info = _view.CalcHitInfo(pt);
if (info.InRow && _view.IsDataRow(info.RowHandle))
UpdateSelection();
if (info.InColumn && info.Column == _column)
{
if (SelectedCount == _view.DataRowCount)
ClearSelection();
else
SelectAll();
}
if (info.InRow && _view.IsGroupRow(info.RowHandle)
&& info.HitTest != GridHitTest.RowGroupButton)
{
bool selected = IsGroupRowSelected(info.RowHandle);
SelectGroup(info.RowHandle, !selected);
}
}
}
private void View_CustomDrawColumnHeader
(object sender, ColumnHeaderCustomDrawEventArgs e)
{
if (e.Column != _column)
return;
e.Info.InnerElements.Clear();
e.Painter.DrawObject(e.Info);
DrawCheckBox(e.Graphics, e.Bounds, SelectedCount == _view.DataRowCount);
e.Handled = true;
}
private void View_CustomDrawGroupRow
(object sender, RowObjectCustomDrawEventArgs e)
{
var info = e.Info as GridGroupRowInfo;
info.GroupText = " " + info.GroupText.TrimStart();
e.Info.Paint.FillRectangle
(e.Graphics, e.Appearance.GetBackBrush(e.Cache), e.Bounds);
e.Painter.DrawObject(e.Info);
var r = info.ButtonBounds;
r.Offset(r.Width * 2, 0);
DrawCheckBox(e.Graphics, r, IsGroupRowSelected(e.RowHandle));
e.Handled = true;
}
private void view_CustomUnboundColumnData
(object sender, CustomColumnDataEventArgs e)
{
if (e.Column != CheckMarkColumn)
return;
if (e.IsGetData)
e.Value = IsRowSelected(View.GetRowHandle(e.ListSourceRowIndex));
else
SelectRow(View.GetRowHandle(e.ListSourceRowIndex), (bool)e.Value);
}
private void edit_EditValueChanged(object sender, EventArgs e)
{
_view.PostEditor();
}
private void SelectRow(int rowHandle, bool select, bool invalidate)
{
if (IsRowSelected(rowHandle) == select)
return;
object row = _view.GetRow(rowHandle);
if (select)
_selection.Add(row);
else
_selection.Remove(row);
if (invalidate)
Invalidate();
OnSelectionChanged(EventArgs.Empty);
}
public object GetSelectedRow(int index)
{
return _selection[index];
}
public int GetSelectedIndex(object row)
{
return _selection.IndexOf(row);
}
public void ClearSelection()
{
_selection.Clear();
View.ClearSelection();
Invalidate();
OnSelectionChanged(EventArgs.Empty);
}
private void Invalidate()
{
_view.CloseEditor();
_view.BeginUpdate();
_view.EndUpdate();
}
public void SelectAll()
{
_selection.Clear();
var dataSource = _view.DataSource as ICollection;
if (dataSource != null && dataSource.Count == _view.DataRowCount)
_selection.AddRange(dataSource); // fast
else
for (int i = 0; i < _view.DataRowCount; i++) // slow
_selection.Add(_view.GetRow(i));
Invalidate();
OnSelectionChanged(EventArgs.Empty);
}
public void SelectGroup(int rowHandle, bool select)
{
if (IsGroupRowSelected(rowHandle) && select) return;
for (int i = 0; i < _view.GetChildRowCount(rowHandle); i++)
{
int childRowHandle = _view.GetChildRowHandle(rowHandle, i);
if (_view.IsGroupRow(childRowHandle))
SelectGroup(childRowHandle, select);
else
SelectRow(childRowHandle, select, false);
}
Invalidate();
}
public void SelectRow(int rowHandle, bool select)
{
SelectRow(rowHandle, select, true);
}
public bool IsGroupRowSelected(int rowHandle)
{
for (int i = 0; i < _view.GetChildRowCount(rowHandle); i++)
{
int row = _view.GetChildRowHandle(rowHandle, i);
if (_view.IsGroupRow(row))
if (!IsGroupRowSelected(row))
return false;
else
if (!IsRowSelected(row))
return false;
}
return true;
}
public bool IsRowSelected(int rowHandle)
{
if (_view.IsGroupRow(rowHandle))
return IsGroupRowSelected(rowHandle);
object row = _view.GetRow(rowHandle);
return GetSelectedIndex(row) != -1;
}
public void UpdateSelection()
{
_selection.Clear();
Array.ForEach(View.GetSelectedRows(), item => SelectRow(item, true));
}
}
And now you need to know how to use this:
void InitGrid()
{
gridControl.DataSource = source;
// Do this after the database for the grid is set!
selectionHelper = new GridCheckMarksSelection(gridView1);
// Define where you want the column (0 = first)
selectionHelper.CheckMarkColumn.VisibleIndex = 0;
// You can even subscrive to the event that indicates that
// there was change in the selection.
selectionHelper.SelectionChanged += selectionHelper_SelectionChanged;
}
void selectionHelper_SelectionChanged(object sender, EventArgs e)
{
// Do something when the user selects or unselects something
}
But how do you retrieve all the selected items? There is a example assuming that the type bond is 'Person'
/// <summary>
/// Return all selected persons from the Grid
/// </summary>
public IList<Person> GetItems()
{
var ret = new List<Person>();
Array.ForEach
(
gridView1.GetSelectedRows(),
cell => ret.Add(gridView1.GetRow(cell) as Person)
);
return ret;
}

Global Variables Return Unexpected Values

Well I was trying to assign global variable to read values from Check boxes and radio buttons but the values don't update when the selections are changed ! Where have I done wrong? Here's the code:
private void chkInMut_Checked(object sender, RoutedEventArgs e)
{
GlobalVar.Mutate = 1;
}
private void chkShwCal_Checked(object sender, RoutedEventArgs e)
{
GlobalVar.ShowCal = 1;
}
private void chkOutSol_Checked(object sender, RoutedEventArgs e)
{
GlobalVar.OutCal = 1;
}
}
public static class GlobalVar
{
static int _MaxMin, _MutVal, _CalShow, _CalOut;
/// <summary>
/// Access routine for global variable.
/// </summary>
public static int Extrema
{
get
{
return _MaxMin;
}
set
{
_MaxMin = value;
}
}
public static int Mutate
{
get
{
return _MutVal;
}
set
{
_MutVal = value;
}
}
public static int ShowCal
{
get
{
return _CalShow;
}
set
{
_CalShow = value;
}
}
public static int OutCal
{
get
{
return _CalOut;
}
set
{
_CalOut = value;
}
}
}
when I try to print the numbers using this test satement, the values returned are unexpected :
maxMin = GlobalVar.Extrema;
calShow = GlobalVar.ShowCal;
calOut = GlobalVar.OutCal;
IsMutble = GlobalVar.Mutate;
txtOutput.Text += Convert.ToString("\nMaxima Minima"+maxMin+"\n"+"Show Cal : "+calShow+"\n"+"Output Cal :"+calOut+"\n"+"Mutate : "+IsMutble+"\n---------\n");
And when I check/un-check the boxes, the values are not updated as it should be. Where have I gone wrong?
Edit: Solved by adding Unchecked Parameter.
Probably you should write your event handlers like this
private void chkInMut_Checked(object sender, RoutedEventArgs e)
{
GlobalVar.Mutate = (chkInMut.IsChecked ? 1 : 0);
}
and so on .....
I think the problem is with your public static properties. for example try this:
public static int Extrema
{
get
{
return GlobalVar._MaxMin;
}
set
{
GlobalVar._MaxMin = value;
}
}
and do the same for all other properties.
Edit:
and why are you using this stucture? You can set your static class to be like this:
public static class GlobalVar
{
public static int Extrema;
public static int Mutate;
public static int ShowCal;
}

Categories

Resources