I'm trying to implement a search suggestion feature using the grid view of Xamarin forms. I was wondering if there is anyway to change the children of the grid dynamically according to the text get entered in the search box.
grid.Children.Add(new Label
{
Text = x.Text,
TextColor = Color.White,
BackgroundColor = Color.Blue
}, 0, x.Id);
If you want to use Grid , then you should specify row ands colums, otherwise all the texts will overlaps each other. Instead of Grid, you should use StackLayout.
hintSL = new StackLayout(){
HorizontalOptions= LayoutOptions.Fill,
//Orientation = Vertical or Horizontal (however you want)
};
//if you want to add hintsSl into your grid
Grid.SetRow(hintsl, 4);
Grid.SetColumn(hintsl, 4);
searchText.Changed+=(s,e)=>{
hintSL.Children.Clear();
foreach(var hint in YourHintsList)
hintsl.Children.Add(new Label(){Text=hint, and other properties});
};
Here are two ways to do this:
The first is to use binding. Bind the text field of the label to a bindable property that changes according to the user's entry.
The second is to make the label a member of whatever class holds the grid, rather than anonymous. Then you can catch the event (eg OnEntryChanged) generated when the user enters the text and dynamically set the label in the code.
Related
I have a form with DataGridViews that have the DataSource set to a DataContext of my database to auto pull in the info and allow it to be edited. But I need a color to display a Color from the color id that corresponds to a color in a colors table and I don't know how I can achieve this with also allowing it to auto edit and update the records.
private dbCounterTopsDataContext dbContext = new dbCounterTopsDataContext();
private void FrmCurrentInventory_Load(object sender, EventArgs e)
{
dataGridColors.DataSource = dbContext.Colors;
dataGridBarTops.DataSource = dbContext.BarTops;
dataGridKitchenTops.DataSource = dbContext.Kitchens;
dataGridVanityTops.DataSource = dbContext.Vanities;
}
I have also tried this and it worked with displaying but I could no longer update directly from the datagrid
private void FrmCurrentInventory_Load(object sender, EventArgs e)
{
dataGridColors.DataSource = dbContext.Colors.Select(o => new { ColorId = o.ColorID, Color = o.Color1 });
dataGridBarTops.DataSource = dbContext.BarTops.Select(o => new { Color = o.Color.Color1, Length = o.Length, Width = o.Width });
dataGridKitchenTops.DataSource = dbContext.Kitchens.Select(o => new { Color = o.Color.Color1, Length = o.Length }).ToList();
dataGridVanityTops.DataSource = dbContext.Vanities;
}
Some good tips in the comments from SSS, perhaps the easiest way to get this going is to use AutogenerateColumns to gen most of the stuff and then add a few combo box columns for your colors. It would probably go something like this:
dataGridColors.DataSource =
dataGridBarTops.DataSource = dbContext.BarTops;
dataGridBarTops.AutogenerateColumns = false;
var c = new DataGridViewComboBoxColumn();
c.HeaderText = "Color";
c.DisplayMember = "Color1"; //name of property that says Blue in color entity
c.ValueMember = "ColorID"; //name of property that says 5 in color/entity
c.DataPropertyName = "BarTopColorId"; //name of property that says 5 in BARTOPS table/entity
c.DataSource = dbContext.Colors; //personally I would use a bindingSource here
dataGridBarTops.Columns.Add(cb);
I'll leave removing the text box color is column as an exercise for you- maybe leave it in first to see how combo is working
The Colors datagridview is for editing the actual Colors definitions etc. The combo box in the bar top table is for choosing a different color is for a single bar top. If you edit the Colors table it will change what is in the list of the combo. If you pick a new combo value it will change the bartop's color id (whatever that property is called) value
Be careful not to edit away ids in Colors that are used in bartops - don't delete color Id 5 from the Colors table while there is still a bartop that uses it
I put a comment there about bindingsources. I've never bound a DGV straight to a LINQ entity list, nor probably would I (partly because it's downloading an entire table, which could be huge and partly because my winforms databinding is near exclusively with strongly typed datasets) but you find it to work (and maybe you need the whole table, no filtering). If, however you start to see strange effects like selecting different rows in the Colors datagridview causes all the combo boxes to change value, bind the combo through a bindingsource so they have something that dedicatedly tracks "the current item" for the combo
I am having problems getting the XAxis to display the correct values in my chart control. Below is how I am generating each series to be displayed. I would like the XAxis to display the DataType value from s.DataType:
foreach (SummaryData s in summaryData)
{
System.Web.UI.DataVisualization.Charting.Series series = new System.Web.UI.DataVisualization.Charting.Series(s.DataType);
series.ChartType = System.Web.UI.DataVisualization.Charting.SeriesChartType.Column;
DataPoint dp = new DataPoint();
dp.Name = s.DataType;
dp.SetValueY(s.Total);
dp.SetCustomProperty("DataType", s.DataType);
series.XValueMember = "DataType";
series.Points.Add(dp);
msBarVertLegRight.Series.Add(series);
}
msBarVertLegRight.DataBind();
The corect value is displayed and the correct name in the Legend, but I'm not exactly sure how to set the XAxis value.
JH
Looks like you're trying to use databinding (which is what the XValueMember is for) and add points one by one. You can do one or the other. You could use databinding like so (approximately):
series.XValueMember = "DataType";
series.YValueMember = "ThePropertyWithY";
series.DataSource = s;
series.DataBind();
or you could set each point individually:
System.Web.UI.DataVisualization.Charting.Series series = new System.Web.UI.DataVisualization.Charting.Series("mySeries");
series.ChartType = System.Web.UI.DataVisualization.Charting.SeriesChartType.Column;
foreach (SummaryData s in summaryData)
{
series.AddXY(s.DataType, s.Total);
}
I'm not sure why you had each SummaryData.DataType being its own series; if that is needed, add that back in, but from the code you posted it didn't seem necessary.
When databinding, any changes to your underlying data (the SummaryData objects) will be reflected in your chart automatically; if you add points individually, you need to handle updates to your chart manually.
Is there any way to get a list view to display vertically? Rigth now for my list view, the view is "List", but if there are too many entries, then you have to scroll to the right to view the rest, I just want to be able to scroll down to see the rest.
I tried all the other options, but they don't seem to work.
Any ideas?
I think to get the effect you want, you need to set the view to "Details", then add a single column (either through the designer or in code).
This is what I do in mine:
SelectionList.View = View.Details;
SelectionList.HeaderStyle = ColumnHeaderStyle.None;
SelectionList.Columns.Add(new ColumnHeader { Width = SelectionList.ClientSize.Width - SystemInformation.VerticalScrollBarWidth });
Then to add items:
foreach (var item in _collectionOfSomething)
{
SelectionList.Items.Add(new ListViewItem(item.ItemName) {Tag = item.Ident});
}
In my application, depending on needs, Some TabPages will be added to a TabControl programatically. Each page will contain a ListView and two ListBoxes:
//Color Picker
var colorBox = new ListBox
{
DataSource = Enum.GetValues(typeof (KnownColor)),
Height = 40,
Width = tabFiles.Width/3,
Dock = DockStyle.Bottom
};
page.Controls.Add(colorBox);
//Style Picker
var styleBox = new ListBox
{
DataSource = Enum.GetValues(typeof(SymbolType)),
Height = 40,
Width = tabFiles.Width / 3,
Dock = DockStyle.Bottom
};
page.Controls.Add(styleBox);
Now later I want to send the selected color and symbol to another class using the code below, it compiles but at runtime it fires invalid cast. How can I fix this?
Color color = (Color)((ListBox)tabFiles.TabPages[i].Controls[1]).SelectedItem;
SymbolType symbol = (SymbolType)((ListBox)tabFiles.TabPages[i].Controls[2]).SelectedItem;
P.S: I know that color and symbol are added to page with index 1 and 2 respectivly.
Thanks.
You are getting a perfectly valid runtime exception. System.Drawing.KnownColor is an enum which you are casting to a System.Drawing.Color which is a struct, they are two very different types.
The hint is in your own code. You are setting the DataSource of your ListBox from an enumeration:
DataSource = Enum.GetValues(typeof (KnownColor))
If you cannot change your data source, I suggest you convert from KnownColor to Color before casting using the Color.FromKnownColor() method.
I am working on a Drag and Drop Editor that is creating items and adding them dynamically to a WPF Canvas. For each item, it is creating a dynamic grid and addign that to the canvas. I need layout state information about each one of these grids as it is added so that I know its coordinates on the canvas. The problem I am having is that when I try to access the Height/ActualHeight/RenderedSize information of each of these Grids that I add, it always turns out to be 0. I am assuming that I might need to render the items so that the new state information is registered, but I am not quite sure how to do this. I have seen support through the InvalidateXXXX() methods that are provided, but I am not sure if/or which one I should be using. there is also an UpdateLayout() function, but I am not sure if this is what I need.
Here is the code that I have running through a loop and adding Grids, which represent LineItems in the Canvas.
/*Initialize Grid Layout*/
Grid newGrid = new Grid();
newGrid.MinHeight = 50;
newGrid.Width = PreviewWindow.ActualWidth;
newGrid.Background = Brushes.Beige;
newGrid.ShowGridLines = true;
/*Define Column Definitions*/
List<ColumnDefinition> columns = new List<ColumnDefinition>(fieldItemList.Count);
foreach (ColumnDefinition column in columns)
{
ColumnDefinition labelColumn = new ColumnDefinition();
newGrid.ColumnDefinitions.Add(labelColumn);
newGrid.ColumnDefinitions.Add(column);
}
/*Define Row Definitions*/
RowDefinition row = new RowDefinition();
newGrid.RowDefinitions.Add(row);
int colCount = 0;
for (int i = 0; i < fieldItemList.Count; i++)
{
FieldItem fieldItem = fieldItemList[i];
/*Initialize Example Label*/
Label label = new Label();
label.Content = fieldItem.Label;
Grid.SetRow(label, 0);
Grid.SetColumn(label, colCount);
newGrid.Children.Add(label);
/*Initialize Example Text Box*/
TextBox textBox = new TextBox();
Grid.SetRow(textBox, 0);
Grid.SetColumn(textBox, colCount + 1);
newGrid.Children.Add(textBox);
colCount++;
}
stackPanel.Children.Add(newGrid);
//I need to Access the Height of each of the grids here somehow
lastTop += (int)newGrid.ActualHeight ;
newGrid.InvalidateMeasure();
//Or InvalidateVisual(), or do I perform this on something else?
}
There is reference to a StackPanel, all of these Grids are being added to a stack panel, and they will eventuall be arranged by the coordinates(which I currently cannot grab). The problem is right now it is adding all these items to a list that will need to be sorted by the Top coordinate, but since the Top coordinate is 0, it will not sort correctly.
A few notes:
The StackPanel does not provide size Layout suggestions to its children, so the Grid will need to supply it's own Layout size. In order for this to work, you'll need to set the Row and Column sizes to "Auto" so that they expand to accommodate their contents. Even then, I'm not entirely sure if this works (usually you combine Auto with "*" rows or columns, rather than having all Auto columns, having them expand to a fixed or stretched overall Grid size.) The layout I've proposed here will behave a bit oddly, as it will dynamically resize columns based on the contents of the column text boxes; for instance, if you have no text in any row, you'll get zero width text boxes with only margin and border providing any size.
Once the StackPanel has had its children added, you'll need to call UpdateLayout on the StackPanel. This will cause it to compute the layout information for each of its children and then position them appropriately. This can become expensive if you keep adding grids dynamically, so fair warning.