ObjectListView - Rows are formatted only after MouseOver on Items - c#

I am in need of some assistance or advice/experience of someone else.
Here is what I'm struggling with:
In my project an objectlistview olvDifference is used to visualize items (Type Conflict) of a list. So far I was able to add the Columns needed and format them properly. But the format provided with
private void ConflictFormatRow(object sender,
BrightIdeasSoftware.FormatRowEventArgs e)
{
Conflict conflict = (Conflict)e.Model;
if (conflict == null) return;
if (conflict.resolution == ConflictResolution.None) e.Item.BackColor = conflictColor;
else if (conflict.resolution == ConflictResolution.UseMine) e.Item.BackColor = mineColor;
else if (conflict.resolution == ConflictResolution.UseTheirs) e.Item.BackColor = theirsColor;
else e.Item.BackColor = System.Drawing.Color.White;
if(e.Model == olvConflictList.SelectedObject)
{
BrightIdeasSoftware.RowBorderDecoration a = new BrightIdeasSoftware.RowBorderDecoration();
a.BorderPen.Color = Color.Black;
a.BorderPen.Width = 3;
a.CornerRounding = 0;
a.FillBrush = Brushes.Transparent;
e.Item.Decoration = a;
}
else
{
BrightIdeasSoftware.RowBorderDecoration b = new BrightIdeasSoftware.RowBorderDecoration();
b.BorderPen.Color = Color.Transparent;
b.BorderPen.Width = 0;
b.CornerRounding = 0;
b.FillBrush = Brushes.Transparent;
e.Item.Decoration = b;
}
}
In the constructor of the form (WFA), the AspectGetter is assigned and the objects to display are set.
Designer-Generated code equals the block below:
//
// olvConflictList
//
this.olvConflictList.AllColumns.Add(this.olvcConflictList);
this.olvConflictList.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.olvConflictList.CellEditUseWholeCell = false;
this.olvConflictList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.olvcConflictList});
this.olvConflictList.Cursor = System.Windows.Forms.Cursors.Default;
this.olvConflictList.FullRowSelect = true;
this.olvConflictList.Location = new System.Drawing.Point(780, 90);
this.olvConflictList.Name = "olvConflictList";
this.olvConflictList.Size = new System.Drawing.Size(286, 489);
this.olvConflictList.TabIndex = 18;
this.olvConflictList.UseCellFormatEvents = true;
this.olvConflictList.UseCompatibleStateImageBehavior = false;
this.olvConflictList.View = System.Windows.Forms.View.Details;
this.olvConflictList.FormatRow += new System.EventHandler<BrightIdeasSoftware.FormatRowEventArgs>(this.ConflictFormatRow);
this.olvConflictList.SelectedIndexChanged += new System.EventHandler(this.olvDifferenceGroups_SelectedIndexChanged);
//
// olvcConflictList
//
this.olvcConflictList.AspectName = "";
this.olvcConflictList.AutoCompleteEditor = false;
this.olvcConflictList.AutoCompleteEditorMode = System.Windows.Forms.AutoCompleteMode.None;
this.olvcConflictList.FillsFreeSpace = true;
this.olvcConflictList.Groupable = false;
this.olvcConflictList.HeaderCheckBoxUpdatesRowCheckBoxes = false;
this.olvcConflictList.Hideable = false;
this.olvcConflictList.IsEditable = false;
this.olvcConflictList.MinimumWidth = 50;
this.olvcConflictList.Searchable = false;
this.olvcConflictList.Sortable = false;
this.olvcConflictList.Text = "Conflicts";
this.olvcConflictList.UseFiltering = false;
this.olvcConflictList.Width = 283;
The only item in the olv has no BackGroundColor (White, default):
After starting the process, it is shown as one can see in the pic above, but I'd expect it to be initialized as in the pic below (after I hovered over it with my mouse the first time).
The only item in the olv has BackGroundColor conflictColor as assigned in the ConflictFormatRow:
Where do I need to improve my code? Any advices?

Well, I could figure it out myself.
I took a look at the source of OLV and what i found out so far:
In my case, the first row, here "Conflicts", was set to "Groupable=False", but the OLV itself was set to "ShowGroups=True".
FormatRow is fired in PostProcessOneRow, which is called according to source (Version: 2.9.1.0) in following logic:
protected virtual void PostProcessRows() {
// If this method is called during a BeginUpdate/EndUpdate pair, changes to the
// Items collection are cached. Getting the Count flushes that cache.
#pragma warning disable 168
// ReSharper disable once UnusedVariable
int count = this.Items.Count;
#pragma warning restore 168
int i = 0;
if (this.ShowGroups) {
foreach (ListViewGroup group in this.Groups) {
foreach (OLVListItem olvi in group.Items) {
this.PostProcessOneRow(olvi.Index, i, olvi);
i++;
}
}
} else {
foreach (OLVListItem olvi in this.Items) {
this.PostProcessOneRow(olvi.Index, i, olvi);
i++;
}
}
}
Since grouping failed, due to no groupable rows being present in OLV, the PostProcessOneRow in the if-body was not hit even once (foreach operated in "this.Groups" whichs count was 0).
Set "ShowGroups=False", works like a charm now.

Related

How to get next value from List<string>

I have problem with List string. I put 3 values into myCollection
List<string> myCollection = new List<string>();
myCollection.Add(Encoding.Default.GetString(data));
myCollection.Add(Encoding.Default.GetString(data2));
myCollection.Add(Encoding.Default.GetString(data3));
and now i have 3 values : A,B,C
but now i want to block buttons with contains this values :
for (var i = 0; i < myCollection.Count; i++)
{
if (myCollection.Contains(A))
{
this.A.Enabled = false;
}
else if (myCollection.Contains(B))
{
this.B.Enabled = false;
}
else if (myCollection.Contains(C))
{
this.C.Enabled = false;
}
}
After this loop just first button=false. Now loop done 3 times this same try block button A and my question is:
How block other buttons?
Now i get in first loop run:
this.A.Enabled = false;
2nd this.A.Enabled = false;
3rd this.A.Enabled = false;
but i want :
1st : this.A.Enabled = false;
2nd : this.B.Enabled = false;
3rd : this.C.Enabled = false;
You don't need a loop for this. Just use simple if statements without else.
if (myCollection.Contains("A"))
this.A.Enabled = false;
if (myCollection.Contains("B"))
this.B.Enabled = false;
if (myCollection.Contains("C"))
this.C.Enabled = false;
Mainly the else was causing problems for you. If the condition for A was true, then the code for B and C did not run. This is how else works.
Not sure what exactly are you trying to achieve, but your problem here is that you use if..else. If any of the conditions is true, the rest won't be resolved.
To solve your problem just remove the else keywords from your conditions.
Also, the loop is unnecesary when you use Contains.
If you'd insist on the loop, you would have to change the condition a bit, and then the else would be properly used:
for (int i = 0; i < myCollection.Count; i++)
{
if (myCollection[i] == A)
{
this.A.Enabled = false;
}
else if (myCollection[i] == B)
{
this.B.Enabled = false;
}
else if (myCollection[i] == C)
{
this.C.Enabled = false;
}
}

Why can't I reach data within Method?

I'm currently trying to fill a TableLayoutPanel through a method which goes as follows:
private int _rowCount;
public void InitPaths()
{
int c = 1;
int a = 1;
while (a < _PathRows.Length - 1)
{
var label = new Label();
//
// Label - Format.
//
label.Dock = DockStyle.Fill;
label.AutoSize = false;
label.Text = _pfadZeilen[a];
label.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
label.Size = new System.Drawing.Size(22, 13);
label.BackColor = System.Drawing.Color.Transparent;
TableLayoutP.Controls.Add(label, 3, c);
//Checkboxen Einfügen
var cbox = new CheckBox();
//
//Checkbox Format.
cbox.Anchor = System.Windows.Forms.AnchorStyles.None;
cbox.AutoSize = true;
cbox.CheckAlign = System.Drawing.ContentAlignment.MiddleCenter;
cbox.Name = "checkBoxPfad" + a;
cbox.Size = new System.Drawing.Size(15, 14);
cbox.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
cbox.UseVisualStyleBackColor = true;
TableLayoutP.Controls.Add(cbox, 0, c);
a++;
c++;
}
this._rowCount = BibTable.GetRowHeights().Length; // which seems to be Holding the value only within the method
}
and then delete all rows on Action, through the following Method:
public void RemoveRows()
{
for (int row = _rowCount; row >= 0; row--)
{
BibTable.RowStyles.RemoveAt(row);
BibTable.RowCount--;
}
}
Now the Problem is, if I try to do anything with the TableLayoutP outside of the method where all rows are initialized, it will tell me:
Object reference not set to the instance of an object.
What can I do? Is there a way to get a method inside a method (I'm realising just how stupid that sounds while typing it) or any other way to deal with this Situation?
You are ittering through GetRowHeights(), returning the height of each row. But you are deleting from the RowStyles collection which is not directly related to the first collection. I assume that GetRowHeights() returns much more rows, than RowStyles has.
Why not:
BibTable.RowCount = 0;
BibTable.RowStyles.Clear();
You are ittering through GetRowHeights(), returning the height of each row. But you are deleting from the RowStyles collection which is not directly related to the first collection. I assume that GetRowHeights() returns much more rows, than RowStyles has.
Why not:
BibTable.RowCount = 0;
BibTable.RowStyles.Clear();

Issues using 2 axis labels with RadBarChart and no Gap between bars

I have 2 problems:
I want the names from the datatable but it is showing me in numeric form.
I would like a gap between the two bars but I can't find a way.
Here is the code:
private void InitializeGraph (DataTable poDt)
{
Telerik.Charting.ChartSeries chartseries = new Telerik.Charting.ChartSeries();
try
{
chartseries.Type = Telerik.Charting.ChartSeriesType.Bar;
Telerik.Charting.ChartSeriesItem csItem;
RadChart1.PlotArea.XAxis.AutoScale = true;
RadChart1.PlotArea.XAxis.DataLabelsColumn = "Name";
for (int iRow = 0; iRow < poDt.Rows.Count; iRow++)
{
chartseries = new Telerik.Charting.ChartSeries();
chartseries.Type = Telerik.Charting.ChartSeriesType.Bar;
chartseries.Name = poDt.Rows[iRow]["Name"].ToString().Trim();
csItem = new Telerik.Charting.ChartSeriesItem();
csItem.Name = poDt.Rows[iRow]["Name"].ToString();
csItem.Label.TextBlock.Text = poDt.Rows[iRow]["Value"].ToString();
RadChart1.PlotArea.XAxis.Appearance.TextAppearance.AutoTextWrap = Telerik.Charting.Styles.AutoTextWrap.True;
csItem.YValue = Int32.Parse(poDt.Rows[iRow]["Value"].ToString());
chartseries.AddItem(csItem);
RadChart1.Series.Add(chartseries);
}
RadChart1.PlotArea.XAxis.AddRange(1, poDt.Rows.Count, 1);
RadChart1.PlotArea.XAxis[poDt.Rows.Count].TextBlock.Text = chartseries.Name;
poDt.Rows.Count.ToString();
RadChart1.PlotArea.XAxis.AutoShrink = false;
RadChart1.PlotArea.XAxis.AutoShrink = true;
RadChart1.Series.Add(chartseries);
RadChart1.PlotArea.Appearance.Border.Visible = false;
RadChart1.Appearance.Border.Visible = true;
RadChart1.PlotArea.YAxis.IsLogarithmic = true;
RadChart1.PlotArea.YAxis.AutoScale = true;
RadChart1.PlotArea.YAxis.Appearance.ValueFormat=Telerik.Charting.Styles.ChartValueFormat.Number;
RadChart1.Appearance.BarWidthPercent = 50;
RadChart1.Chart.Appearance.FillStyle.MainColor = System.Drawing.Color.Red;
RadChart1.Chart.Appearance.FillStyle.MainColor = System.Drawing.Color.Transparent;
RadChart1.Legend.Appearance.FillStyle.MainColor = System.Drawing.Color.Transparent;
}
catch (Exception Ex)
{
//throw;
}
finally
{
poDt.Clear();
poDt = null;
chartseries = null;
}
}
Sorry, I do not believe there is a way to display two X-axis at the same time.
My suggestion is you use a CategoricalAxis for your X axis and create a custom bar chart that has a legend which differentiates the two values. I don't have any working samples, however you can use this Telerik Silverlight demo for starters.
Also, switch to RadChartView if you can. Because I would then suggest an easier approach, which is using a Categorical X-Axis and create multiple Y axes. If you go that route, you can do something like this for a DateTimeContinuous (or Categorical) X-axis with multiple Y-axes :
int count = 0;
LineSeries lineSeries = new LineSeries();
lineSeries.CategoryBinding = new PropertyNameDataPointBinding() { PropertyName = "TimeStamp" };
lineSeries.ValueBinding = new PropertyNameDataPointBinding() { PropertyName = "Value" };
lineSeries.VerticalAxis = new LinearAxis()
{
Title = "Title Here"
};
lineSeries.ItemsSource = yourCollection.Values;
//First Y-axis to be placed on the left of X-axis,
//additional Y-axes to be placed on right
if (count > 0 )
{
lineSeries.VerticalAxis.HorizontalLocation = Telerik.Charting.AxisHorizontalLocation.Right;
}
count++;
chartName.Series.Add(lineSeries);
Hope this helps.

C# reassigning array values(down one step ex 5-4) that are within an object during a event

Just learning C# (along with object and event programing) and the teacher didn't really show us how to get things done.
class Postion
{
private int[] x_coordinate = new int[100];
private int[] y_coordinate = new int[100];
private double[] speed = new double[100];
private int[] direction = new int[100];
const int MAX_SPEED = 50;
int counter = 0;
public Postion()
{
x_coordinate[counter] = 0;
y_coordinate[counter] = 0;
speed[counter] = 0;
direction[counter] = 0;
}
//get set methods
public int X
{
get
{
return x_coordinate[counter];
}
set
{
x_coordinate[counter] = value;
}
}
There is one more Class between them
The values are frist assigned by a button click.
Airplane newplane = new Airplane();
private void BtnCreate_Click(object sender, EventArgs e)
{
bool box = txtName.Text != "";
if (box == true)
newplane.Name = txtName.Text;
else { }
box = txtx.Text != "";
if (box == true)
newplane.PlanePostion.X = int.Parse(txtx.Text);
else { }
Etc.
I can call on the array values for display for the list box.
private void lsbplanes_SelectedIndexChanged(object sender, EventArgs e)
{
placeholder = newplane.PlanePostion.Counter;
newplane.PlanePostion.Counter = lsbplanes.SelectedIndex;
if (newplane.PlanePostion.Counter < 0)
newplane.PlanePostion.Counter = 0;
else { }
lblxshow.Text = Convert.ToString(newplane.Getx());
but when using a destroy button to remove an item in the list box I need to have it so the box updates with the new values when the user selects the item in the listbox.
This is what I have to try and do it so far, it sets all the ones above to 0s but does remove the the deleted one fine
private void BtnKill_Click(object sender, EventArgs e)
{
if (lsbplanes.SelectedIndex == -1)
{
MessageBox.Show("Please select an item first.", "No item selected", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
else
{
placeholder = lsbplanes.SelectedIndex;
newplane.PlanePostion.Counter = lsbplanes.Items.Count;
while (newplane.PlanePostion.Counter > placeholder)
{
placex = newplane.PlanePostion.X;
placey = newplane.PlanePostion.Y;
placespeed = newplane.Getspeed();
placedic = newplane.Getdirection();
newplane.PlanePostion.Counter--;
newplane.PlanePostion.X = placex;
newplane.PlanePostion.Y = placey;
newplane.PlanePostion.Speed = placespeed;
newplane.PlanePostion.Direction = placedic;
}
lsbplanes.Items.RemoveAt(lsbplanes.SelectedIndex);
newplane.PlanePostion.Counter = lsbplanes.Items.Count;
}
anyone can help me on this?
I was torn in this question, answer exactly what your problem is, or suggest that you redesign it.
#Marc is right you should be using some sort of List<Position> on your Plane object (or a ReadOnlyObservableCollection<Position>).
#Marc is also right, that the problem you are having is that you are trying to push the values down from the end of the list and overwriting them. In these cases it is better to start from the deletion point and pull them down.
So if you have {1,2,3,4,5,6,7,8,9,10} and you delete from item 5, you would have {1,2,3,4,10,10,10,10,10,10}. The code below will let you end up with {1,2,3,4,6,7,8,9,0}
placeholder = lsbplanes.SelectedIndex;
int idx = placeholder;
while (idx < lsbplanes.Items.Count)
{
newplane.PlanePosition.Counter = idx+1;
placex = newplane.PlanePostion.X;
placey = newplane.PlanePostion.Y;
placespeed = newplane.Getspeed();
placedic = newplane.Getdirection();
newplane.PlanePostion.Counter = idx;
newplane.PlanePostion.X = placex;
newplane.PlanePostion.Y = placey;
newplane.PlanePostion.Speed = placespeed;
newplane.PlanePostion.Direction = placedic;
idx++;
}
// Need to zero out elements at the end
newplant.PlanePosition.Counter = lsbplanes.Items.Count;
/* Zeroing code goes here */
newplane.PlanePosition.Counter = placeholder;
lsbplanes.Items.RemoveAt(lsbplanes.SelectedIndex);

how to loop through some ASP.NET labels to set their attributes?

How do I do this in a loop.
protected void ddlTool_SelectedIndexChanged(object sender, EventArgs e)
{
lblTool1.Visible = false;
txtTool1.Visible = false;
lblTool2.Visible = false;
txtTool2.Visible = false;
lblTool3.Visible = false;
txtTool3.Visible = false;
lblTool4.Visible = false;
txtTool4.Visible = false;
lblTool5.Visible = false;
if (ddlTool.SelectedValue == "1")
{
lblTool1.Visible = true;
txtTool1.Visible = true;
}
if (ddlTool.SelectedValue == "2")
{
lblTool1.Visible = true;
txtTool1.Visible = true;
lblTool2.Visible = true;
txtTool2.Visible = true;
}
if (ddlTool.SelectedValue == "3")
{
lblTool1.Visible = true;
txtTool1.Visible = true;
lblTool2.Visible = true;
txtTool2.Visible = true;
lblTool3.Visible = true;
txtTool3.Visible = true;
}
if (ddlTool.SelectedValue == "4")
{
lblTool1.Visible = true;
txtTool1.Visible = true;
lblTool2.Visible = true;
txtTool2.Visible = true;
lblTool3.Visible = true;
txtTool3.Visible = true;
lblTool4.Visible = true;
txtTool4.Visible = true;
}
Instead of having a separate variable for each textbox and label, have a collection of them - whether that's a List<T> or an array or whatever.
Then you can do:
// Potentially use int.TryParse here instead
int visibleLabels = int.Parse(ddlTool.SelectedValue);
for (int i = 0; i < labels.Count; i++)
{
labels[i].Visible = (i < visibleLabels);
textBoxes[i].Visible = (i < visibleLabels);
}
(Alternatively use two loops, one to set some Visible properties to true, and one to set some to false.)
You can access a control by its name using
container.Controls["nameofcontrol"]
So technically, you could use this to lookup your control
(Untested code)
for(int index = 1; index <= Convert.ToInt32(ddlTool.SelectedValue); index++)
{
this.Controls["lblTool" + index.ToString()].Visible = true;
this.Controls["txtTool" + index.ToString()].Visible = true;
}
Use a UserControl for each set of connected controls and then enable/disable the UserControl instead of all the component controls. This is classic, basic modularization of your user interface.
Note that this will still require a little "redundant" code because you're working with an unusual UI paradigm by enabling up-to the ddlTool's selected value of your control. E.g., create your user control that contains a single Label and TextBox. Call it LabeledTextBox or something similar. Then you'd create a collection of your labeled text boxes and enable them up to int.Parse(ddlTool.SelectedValue) - 1.
foreach (Control ctrl in this.Controls)
{
int index = (int)ctrl.Name.Substring(ctrl.Name.Length - 1);
int maxIndex = (int)ddlTool.SelectedValue;
ctrl.Visible = (index <= maxIndex);
}
Here is an example with no error checking, but should match your code functionality.
protected void ddlTool_SelectedIndexChanged(object sender, EventArgs e)
{
int selectedValue = int.Parse(ddlTool.SelectedValue.ToString());
for (int i = 1; i <= 4; ++i)
{
bool state = i <= selectedValue;
this.Controls["lblTool" + i.ToString()].Visible = state;
this.Controls["txtTool" + i.ToString()].Visible = state;
}
}

Categories

Resources