I'm having some trouble with my WPF Form.
I have a list of objects, those objects have properties for Name, Value, IsRequired, Type (either bool, string or Datepicker).
So my list could have any number of objects and they could be either bool string etc.
I have created a custom control that propagates through this list and builds the form with the relevant controls such as CheckBox if its a bool and TextBox if its a string.
So far the code i have to generate this is like so, I have placed the controls in a grid for layout.
private object GetCustomElement(DicomMetadataModel metadata)
{
Grid dynamicGrid = new Grid() { VerticalAlignment = VerticalAlignment.Center };
dynamicGrid.Background = new SolidColorBrush(Colors.Transparent);
// Margin order LTRB
dynamicGrid.Margin = new Thickness(10, 3, 10, 3);
// Grid Definitions
ColumnDefinition col1 = new ColumnDefinition();
col1.Width = new GridLength(2, GridUnitType.Star);
ColumnDefinition col2 = new ColumnDefinition();
col2.Width = new GridLength(5, GridUnitType.Star);
RowDefinition gridRow1 = new RowDefinition();
gridRow1.Height = new GridLength(47);
dynamicGrid.ColumnDefinitions.Add(col1);
dynamicGrid.ColumnDefinitions.Add(col2);
dynamicGrid.RowDefinitions.Add(gridRow1);
//Label
var label = new Label()
{
FontSize = 15,
MinHeight = 12,
VerticalContentAlignment = VerticalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0),
Foreground = new SolidColorBrush(_lblTextColor)
};
label.Content = new TextBlock() { TextWrapping = TextWrapping.WrapWithOverflow, Text = metadata.Label };
Grid.SetRow(label, 0);
Grid.SetColumn(label, 0);
dynamicGrid.Children.Add(label);
if (metadata.Type == typeof(string) || metadata.Type == typeof(int))
{
//Textbox
var textBox = new TextBox()
{
MinWidth = 150,
MinHeight = 20,
Padding = new Thickness(5),
FontSize = 16,
Foreground = new SolidColorBrush(_lblTextColor),
BorderBrush = new SolidColorBrush(_tbBorderColor),
Background = new SolidColorBrush(_tbBackgroundColor)
};
textBox.IsReadOnly = IsReadOnly;
Grid.SetRow(textBox, 0);
Grid.SetColumn(textBox, 1);
dynamicGrid.Children.Add(textBox);
}
else if (metadata.Type == typeof(bool))
{
//RadioButton
var stack = new WrapPanel();
var view = new Viewbox() { MaxWidth = 30, Margin = new Thickness(10) };
var radioButton = new RadioButton()
{
Background = new SolidColorBrush(_tbBackgroundColor),
BorderBrush = new SolidColorBrush(_tbBorderColor),
BorderThickness = new Thickness(1),
Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF7373"))
};
view.Child = radioButton;
stack.Children.Add((UIElement)view);
Grid.SetRow(stack, 0);
Grid.SetColumn(stack, 1);
dynamicGrid.Children.Add(stack);
}
return dynamicGrid;
}
This code is to create each element, this is recursively called in the following method
private void LoadViewerStudyInformation()
{
var dicomMetadata = DataContext as List<DicomMetadataModel>;
if (dicomMetadata == null)
{
throw new InvalidOperationException();
}
int count = 0;
foreach (var metadata in dicomMetadata)
{
if (!metadata.IsVisible)
{
continue;
}
else if(count < 5)
{
Children.Add((UIElement)GetCustomElement(metadata));
count++;
}
Margin = new Thickness(10);
Orientation = Orientation.Vertical;
}
// TODO build control, bind field to DataContext models
// TODO how result of control is bound to DataContext model Result property
}
This creates the the form as i would like it to appear on the screen.
I am having trouble now however hooking up the data entered and binding it to some model to store the information off.
I can hook up to the textbox TextChanged events but when it is fired there is not indication as to what property it should store to.
Will i need to create a new class say that has maybe a textbox and label property in it and call it like so , myClass.Textbox.Text etc.
MetaDataDicomModel here is like so
public class DicomMetadataModel
{
public string Value { get; set; }
public string Label { get; set; }
public Type Type { get; set; }
public bool IsRequired { get; set; }
public bool IsVisible { get; set; }
public bool IsReadOnly { get; set; }
}
I don't want to create something overly complicated because of a lack of understanding, if anyone could suggest the best way to do it i would be very grateful.
Related
I am using Telerik (RadPieChart) with WPF. What I want to do is add a small space between the bars. I am not asking about the space between the series, as that is already available, but about a smaller space between the bars just as shown in the image examples below.
Here is what I have now:
And this is how I would like my Bar Chart to look like with a small space between them:
This is my source code:
private BarSeries CreateBarSeries(KeyValuePair<ChartSerie, List<ChartDataPoint>> chartSeries, ChartLegendSettings legendSettings, int colorPaletteIndex)
{
var isStackMode = chartSeries.Key.CombineMode == SeriesCombineMode.Stack;
var barSerie = new BarSeries()
{
VerticalAxis = CreateMultipleVerticalAxis(chartSeries, colorPaletteIndex, out var multipleVerticalAxis) ? multipleVerticalAxis : null,
LegendSettings = legendSettings,
StackGroupKey = chartSeries.Key.Group,
Opacity = 0.8,
ZIndex = 120,
CombineMode = string.IsNullOrEmpty(chartSeries.Key.Group)
? ChartSeriesCombineMode.Cluster
: (isStackMode ? ChartSeriesCombineMode.Stack : ChartSeriesCombineMode.Stack100),
// start animations
//PointAnimation = new ChartMoveAnimation()
//{
// MoveAnimationType = MoveAnimationType.Bottom,
// Duration = new TimeSpan(0, 0, 0, 0, 600),
// Delay = new TimeSpan(0, 0, 0, 0, 155),
// //Easing = new ElasticEase()
// //{
// // EasingMode = EasingMode.EaseOut,
// //},
//},
LabelDefinitions =
{
// set the clarion format for the labels
new ChartSeriesLabelDefinition()
{
Template = new DataTemplate()
{
VisualTree = GetSeriesFormat(chartSeries),
}
}
}
};
// this is the color of bar series
if (chartSeries.Key.ColorHex != null)
{
Style style = new Style(typeof(Border));
style.Setters.Add(new Setter(Border.BackgroundProperty, (SolidColorBrush)(new BrushConverter().ConvertFrom(chartSeries.Key.ColorHex))));
barSerie.DefaultVisualStyle = style;
}
foreach (ChartDataPoint serie in chartSeries.Value)
{
barSerie.DataPoints.Add(new CategoricalDataPoint()
{
Category = serie.XPoint.Label,
Value = (double?)serie.Value,
});
}
return barSerie;
}
The answer:
For some reason adding the BorderThickness to the Style as suggested in one of the answers did not do the trick, although BorderThicknes should be the solution. So I added a PointTemplate with a VisualTree and there I defined the BorderThickness. Now it is working perfectly.
private BarSeries CreateBarSeries(KeyValuePair<ChartSerie, List<ChartDataPoint>> chartSeries, ChartLegendSettings legendSettings, int colorPaletteIndex)
{
var seriesPredefinedColor = this.ChartBase.Palette.GlobalEntries[colorPaletteIndex].Fill;
FrameworkElementFactory borderFramework = new FrameworkElementFactory(typeof(Border));
borderFramework.SetValue(Border.BackgroundProperty, ColorService.BrushFromHex(chartSeries.Key.ColorHex) ?? seriesPredefinedColor);
borderFramework.SetValue(Border.OpacityProperty, 0.8D);
borderFramework.SetValue(Border.BorderThicknessProperty, new Thickness(2));
borderFramework.AddHandler(Border.MouseEnterEvent, new MouseEventHandler((sender, args) =>
{
var seriesBorder = (Border)sender;
//seriesBorder.BorderBrush = new SolidColorBrush(Colors.Black);
//seriesBorder.BorderThickness = new Thickness(1);
seriesBorder.Opacity = 1;
}));
borderFramework.AddHandler(Border.MouseLeaveEvent, new MouseEventHandler((sender, args) =>
{
var seriesBorder = (Border)sender;
//seriesBorder.BorderBrush = new SolidColorBrush(Colors.Black);
//seriesBorder.BorderThickness= new Thickness(1);
seriesBorder.Opacity = 0.8;
}));
var isStackMode = chartSeries.Key.CombineMode == SeriesCombineMode.Stack;
var barSerie = new BarSeries()
{
VerticalAxis = CreateMultipleVerticalAxis(chartSeries, colorPaletteIndex, out var multipleVerticalAxis) ? multipleVerticalAxis : null,
LegendSettings = legendSettings,
StackGroupKey = chartSeries.Key.Group,
ZIndex = 120,
IsHitTestVisible = true,
CombineMode = string.IsNullOrEmpty(chartSeries.Key.Group)
? ChartSeriesCombineMode.Cluster
: (isStackMode ? ChartSeriesCombineMode.Stack : ChartSeriesCombineMode.Stack100),
// start animations
//PointAnimation = new ChartMoveAnimation()
//{
// MoveAnimationType = MoveAnimationType.Bottom,
// Duration = new TimeSpan(0, 0, 0, 0, 600),
// Delay = new TimeSpan(0, 0, 0, 0, 155),
// //Easing = new ElasticEase()
// //{
// // EasingMode = EasingMode.EaseOut,
// //},
//},
LabelDefinitions =
{
// set the clarion format for the labels
new ChartSeriesLabelDefinition()
{
Template = new DataTemplate()
{
VisualTree = GetSeriesFormat(chartSeries),
}
}
},
PointTemplate = new DataTemplate()
{
VisualTree = borderFramework,
}
};
// this is the color of bar series
//if (chartSeries.Key.ColorHex != null)
//{
// Style style = new Style(typeof(Border));
// style.Setters.Add(new Setter(Border.BackgroundProperty, (SolidColorBrush)(new BrushConverter().ConvertFrom(chartSeries.Key.ColorHex))));
// barSerie.DefaultVisualStyle = style;
//}
foreach (ChartDataPoint serie in chartSeries.Value)
{
barSerie.DataPoints.Add(new CategoricalDataPoint()
{
Category = serie.XPoint.Label,
Value = (double?)serie.Value,
});
}
return barSerie;
}
Set the BorderThickness property of the DefaultVisualStyle of the BarSeries:
// this is the color of bar series
if (chartSeries.Key.ColorHex != null)
{
Style style = new Style(typeof(Border));
style.Setters.Add(new Setter(Border.BackgroundProperty, (SolidColorBrush)(new BrushConverter().ConvertFrom(chartSeries.Key.ColorHex))));
style.Setters.Add(new Setter(Border.BorderThicknessProperty, new Thickness(2.0)));
barSerie.DefaultVisualStyle = style;
}
have you look into this ? seem default is 0 mean bar take all the space
Scale.SpacingSlotCount Property
Determines the number of space slots that will be left around the DataPoints per category slot, measured relatively to the DataPoint
slot's width: Empty Space = SpacingSlotCount * DataPoint_SlotWidth
Namespace: Telerik.Reporting
Assembly: Telerik.Reporting (in Telerik.Reporting.dll) Version: 12.1.18.816 (12.1.18.816)
My aim is to create a .dll file dynamically having TextBox,Button which can be used by anyone in a program using Visual C#.
It would get created in Class Library, No WFA tools would get used.
I need help in creating a form which can generate multiple TextBox according to the attributes provided by the user.
1)No of TextBox
2)Location
3)Size etc
Code
CLASS.CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
namespace Forms
{
public class TextForm : Form
{
public TextBox txtBox1;
public TextForm(int a, int b, int c, int d, string e)
{
Form f1 = new Form();
txtBox1 = new TextBox();
txtBox1.Visible = true;
//f1.ActiveControl=txtBox1;
f1.Controls.Add(txtBox1);
txtBox1.Focus();
f1.Visible = true;
txtBox1.Size = new Size(a, b);
txtBox1.Location = new Point(c, d);
txtBox1.Text = (e).ToString();
this.Controls.Add(txtBox1);
txtBox1.Visible = true;
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
}
}}
PROGRAM.CS
using System;
using Forms;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
TextForm Box1 = (new TextForm(150, 14, 20, 32, "This is a TextBox 1"));
TextForm Box2 = (new TextForm(180, 34, 40, 52, "This is a TextBox 2"));
}}}
What should be the code?
The problem is that you are creating a Form for each TextBox. This is not what you want, provided that you plan to have forms with multiple text boxes.
I see two possibilities: you either want to create a) a textbox that you can easily add to your form, or b) a form with textboxes.
public class TextInput : Form
{
public TextBox TxtBox {
get; private set;
}
public Control Container {
get; private set;
}
public TextInput(Control c, int a, int b, int c, int d, string e)
{
this.Container = c;
this.TxtBox = new TextBox();
var txtBox1 = this.TxtBox;
txtBox1.Visible = true;
c.Controls.Add(txtBox1);
txtBox1.Focus();
txtBox1.Size = new Size(a, b);
txtBox1.Location = new Point(c, d);
txtBox1.Text = (e).ToString();
txtBox1.Visible = true;
}
}
You'd use this as follows:
var f = new Form();
var txtBox1 = new TextInput( f, 100, 25, 10, 10, "Name" );
var txtBox1 = new TextInput( f, 100, 25, 10, 50, "Age" );
var txtBox1 = new TextInput( f, 100, 25, 10, 100, "Address" );
var txtBox1 = new TextInput( f, 100, 25, 10, 150, "Phone" );
The second possibility is much more interesting, in my opinion. You want to create a special Form that automatically adds text boxes as soon a you call a simple method. I'm going to simplify your code, though. It is not a good idea (at all), to use absolute positioning in your forms.
The following creates a form with text boxes and their labels. The textboxes occupy the whole width of the form. This is achieved by using a TableLayoutPanel in which a Panel subPanel is used for each row.
This subPanel holds a label and a text box.
public class InputForm: Form {
public InputForm()
{
this.Panel = new TableLayoutPanel{ Dock = DockStyle.Fill };
this.textBoxes = new List<TextBox>();
this.Controls.Add( this.Panel );
}
public TextBox AddTextBox(string label)
{
var subPanel = new Panel { Dock = DockStyle.Top };
var lblLabel = new Label { Text = label, Dock = DockStyle.Left };
var tbEdit = new TextBox{ Dock = DockStyle.Fill };
subPanel.Controls.Add( tbEdit );
subPanel.Controls.Add( lblLabel );
this.Panel.Controls.Add( subPanel );
return tbEdit;
}
public TableLayoutPanel Panel {
get; private set;
}
public TextBox[] TextBoxes {
get {
return this.textBoxes.ToArray();
}
}
private List<TextBox> textBoxes;
}
You can use this with the following simple code:
var form = new InputForm();
var tbName = form.AddTextBox( "Name" );
var tbAge = form.AddTextBox( "Age" );
var tbAddress = form.AddTextBox( "Address" );
form.Show();
Application.Run( form );
If you'd like to give a few attributes to the text boxes to be created (colors, font, bold...), then you have two ways. The first one is to add parameters to the AddTextBox() method, though that would not scalate well as long as the number of attributes grows. The alternative is to create a TextBoxAttributes class, which will hold the configuring attributes for a given TextBox.
public class InputForm: Form {
public class TextBoxAttributes {
public TextBoxAttributes() {
this.ForeColor = DefaultForeColor;
this.BackColor = DefaultBackColor;
this.Font = DefaultFont;
}
public Color ForeColor {
get; set;
}
public Color BackColor {
get; set;
}
public Font Font {
get; set;
}
public bool Bold {
get {
return this.Font.Bold;
}
set {
var style = FontStyle.Regular;
if ( value ) {
style = FontStyle.Bold;
}
this.Font = new Font( this.Font, style );
}
}
public bool Italic {
get {
return this.Font.Bold;
}
set {
var style = FontStyle.Regular;
if ( value ) {
style = FontStyle.Italic;
}
this.Font = new Font( this.Font, style );
}
}
public bool Underline {
get {
return this.Font.Bold;
}
set {
var style = FontStyle.Regular;
if ( value ) {
style = FontStyle.Underline;
}
this.Font = new Font( this.Font, style );
}
}
public float FontSize {
get {
return this.Font.Size;
}
set {
this.Font = new Font( this.Font.FontFamily, value );
}
}
}
// ... more things...
public TextBox AddTextBox(string label)
=> this.AddTextBox( label, new TextBoxAttributes() );
public TextBox AddTextBox(string label, TextBoxAttributes attr)
{
var subPanel = new Panel { Dock = DockStyle.Top };
var lblLabel = new Label { Text = label, Dock = DockStyle.Left };
var tbEdit = new TextBox{
Dock = DockStyle.Fill,
ForeColor = attr.ForeColor,
BackColor = attr.BackColor,
Font = attr.Font
};
subPanel.Controls.Add( tbEdit );
subPanel.Controls.Add( lblLabel );
this.Panel.Controls.Add( subPanel );
return tbEdit;
}
// ... more things...
}
The main code would be:
public static void Main()
{
var form = new InputForm();
var tbName = form.AddTextBox( "Name", new InputForm.TextBoxAttributes {
ForeColor = Color.Yellow,
BackColor = Color.Blue
});
var tbAge = form.AddTextBox( "Age", new InputForm.TextBoxAttributes {
ForeColor = Color.Green,
BackColor = Color.Black,
Bold = true
});
var tbAddress = form.AddTextBox( "Address" );
form.Show();
Application.Run( form );
}
Hope this helps.
If you are willing to switch to WPF this will become a lot easier, since you can profit from Autolayout and Bindings.
You could easily switch the Wrappanel for a StackPanel or a DockPanel.
The class will create a View based on the public properties of the handed over object. You might have to add additional Types to the Types-Dictionary. In my case those two where sufficient.
Create a Property of the DynamicControl and Bind to it in XAML.
XAML:
<ContentPresenter Content="{Binding Path=DynView}" />
public ViewModel
{
public UserControl DynView {get; private set};
private ModelType _model;
public ViewModel(ModelType model)
{
_model = model;
DynView = new DynamicControl<ModelType>(_model);
}
}
public class DynamicControl<T> : UserControl
{
static DynamicControl()
{
Types[typeof(bool)] = (binding) =>
{
CheckBox cb = new CheckBox();
cb.SetBinding(CheckBox.IsCheckedProperty,binding);
return cb;
};
Types[typeof(String)] = (binding) =>
{
TextBox tb = new TextBox();
tb.SetBinding(TextBox.TextProperty, binding);
return tb;
};
// add additional Types if necessary
}
private T _model;
public DynamicControl(T model)
{
_model = model;
WrapPanel wp = new WrapPanel();
foreach (PropertyInfo pi in model.GetType().GetProperties())
{
Grid g = new Grid();
g.Margin = new Thickness(5, 5, 25, 5);
g.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
g.ColumnDefinitions.Add(new ColumnDefinition());
g.ColumnDefinitions.Add(new ColumnDefinition());
g.RowDefinitions.Add(new RowDefinition());
TextBlock tb = new TextBlock() { Text = pi.Name };
tb.VerticalAlignment = VerticalAlignment.Center;
Grid.SetColumn(tb, 0);
Grid.SetRow(tb, 0);
g.Children.Add(tb);
System.Windows.FrameworkElement uie = GetUiElement(pi);
uie.Margin = new Thickness(10, 0, 0, 0);
uie.VerticalAlignment = VerticalAlignment.Center;
Grid.SetColumn(uie, 1);
Grid.SetRow(uie, 0);
g.Children.Add(uie);
wp.Children.Add(g);
}
this.Content = wp;
}
private FrameworkElement GetUiElement(PropertyInfo pi)
{
System.Windows.Data.Binding binding = new System.Windows.Data.Binding(pi.Name);
binding.Source = _model;
Func<System.Windows.Data.Binding, FrameworkElement> func;
FrameworkElement uie = null;
if (Types.TryGetValue(pi.PropertyType, out func))
uie = func(binding);
else
uie = Types[typeof(String)](binding);
return uie;
}
private static Dictionary<Type, Func<System.Windows.Data.Binding, FrameworkElement>> Types = new Dictionary<Type, Func<System.Windows.Data.Binding, FrameworkElement>>();
}
I think you're going at this all wrong. Just define your dimensions and text in advance, put them in a data class, and then feed a list of those data classes to your form constructor so it can construct them all on the fly.
The data class:
public class TextboxInfo
{
public Int32 Width { get; set; }
public Int32 Height { get; set; }
public Int32 X { get; set; }
public Int32 Y { get; set; }
public String Text { get; set; }
public TextboxInfo(Int32 w, Int32 h, Int32 x, Int32 y, String text)
{
this.Width = w;
this.Height = h
this.X = x;
this.Y = y
this.Text = text;
}
}
The code to construct the form:
public class TextForm : Form
{
public TextBox[] TextBoxes
{
get { return _textBoxes.ToArray(); }
}
private List<TextBox> _textBoxes;
public TextForm(TextboxInfo[] textboxes, Int32 padX, Int32 padY)
{
_textBoxes = new List<TextBox>();
Int32 reqWidth = 0;
Int32 reqHeight = 0;
foreach (TextboxInfo tbi in textboxes)
{
reqWidth = Math.Max(reqWidth, tbi.X + tbi.Width);
reqHeight = Math.Max(reqHeight, tbi.Y + tbi.Height);
TextBox txtB = new TextBox();
txtB.Size = new Size(tbi.Width, tbi.Height);
txtB.Location = new Point(tbi.X, tbi.Y);
txtB.Text = tbi.Text;
_textBoxes.Add(txtB);
this.Controls.Add(txtB);
}
// You may want to add some kind of OK button at the end here (based on reqHeight)
// and link that to a click listener that closes the form.
// Don't forget to adjust your reqHeight to the added height of that button!
// ...
// Set form to the minimum needed size according to its elements.
this.Size = new Size(reqWidth + padX, reqHeight + padY);
}
}
The calling code:
class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
TextboxInfo[] info = new TextboxInfo[2];
info[0] = new TextboxInfo(150, 14, 20, 32, "This is a TextBox 1");
info[1] = new TextboxInfo(180, 34, 40, 52, "This is a TextBox 2");
TextForm frm = new TextForm(info, 20, 32);
frm.ShowDialog();
// Now you can access the form's text box values through frm.TextBoxes[i].Text
}
}
Mind you, this whole system may seem useful at first, but consider that none of the text boxes have labels on them. Just starting values.
I've made systems for custom data before in a project I created, to generate a custom save options dialog depending on the chosen file type to save to, since each file type needed specific options.
Realistically, you'd create a form with some kind of description at the top and an OK and a Cancel button at the bottom, with a panel in between which has its vertical scrollbar set to enable-when-needed. Then you can dynamically put different custom controls in there to support different data types, like say, a checkbox, a text field, a numeric field, et cetera. They'll automatically be listed vertically in the list simply by keeping track of each control's height to get the next control's Y-offset, and if they'd exceed the form size the panel will make sure you can scroll down.
All you'd give to the form are objects of a data class like the one I showed, but without positioning data. They'd have a type, to figure out what kind of custom control to create, a description text, a default value to set the input control to, and possibly some kind of initialisation value, for example, to limit the range of a numeric value, or, as in the image I showed, values for a dropdown list.
first of all sorry for the mess, I'm kicking my head in this for a while already, I'm kind new in xamarin and starting with difficult problems. I'm trying to add dynamically a list of random images in a grid.
currently i have the grid printing like
Name1 Detail1
filename1 filename2 filename3
Name2 Detail2
Filename1 filename2
var cell = new DataTemplate(() => {
var grid = new Grid() { Padding = 8, RowSpacing = 5, ColumnSpacing = 5 };
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(50, GridUnitType.Star) });
Subtitle.SetBinding(Label.TextProperty, "Images");
grid.Children.Add(labelName, 0, 0);
grid.Children.Add(labelDetail, 1, 0);
grid.Children.Add(Subtitle, 1, 1);
the cell in the end is attached to a listview
listdata.ItemTemplate = cell;
in the Object I have defined images as a string, I already tried to create another bind to a list, and create a listview of a custom call and add it to the grid, but throws an error and I can't see any description, it's something like sigsegv-without-stack trace
Also tried to instead of a grid, create a stack layout. again nothing.
CustomCell
public class CustomNocCell : ViewCell
{
public CustomCell()
{
//instantiate each of our views
var image = new Image();
var nameLabel = new Label();
var typeLabel = new Label();
var verticaLayout = new StackLayout();
var horizontalLayout = new StackLayout() { BackgroundColor = Color.Transparent };
//set bindings
nameLabel.SetBinding(Label.TextProperty, new Binding("Name"));
image.SetBinding(Image.SourceProperty, new Binding("Image"));
//Set properties for desired design
horizontalLayout.Orientation = StackOrientation.Horizontal;
horizontalLayout.HorizontalOptions = LayoutOptions.Center;
image.HorizontalOptions = LayoutOptions.End;
nameLabel.FontSize = 24;
//add views to the view hierarchy
verticaLayout.Children.Add(nameLabel);
horizontalLayout.Children.Add(verticaLayout);
horizontalLayout.Children.Add(image);
// add to parent view
View = horizontalLayout;
}
}
what I tried already that gave the error
//ListView listView = new ListView();
//listView.RowHeight = 60;
//listView.ItemTemplate = new DataTemplate(typeof(CustomNocCell));
////listView.ItemsSource = "ImagesNoc";
//listView.SetBinding(ListView.ItemsSourceProperty, "ImagesList");
ImagesList class
[Ignore]
public ListView ImagesList
{
get
{
ListView listView = new ListView();
listView.RowHeight = 60;
listView.ItemTemplate = new DataTemplate(typeof(CustomNocCell));
List<string> list = new List<string>();
if (!string.IsNullOrEmpty(Detail))
{
foreach (string str in Detail.Split(';'))
{
list.Add(str);
}
}
listView.ItemsSource = list.Select(s => new { Name = s, Image = s.ToLower() + ".png" }).ToList();
return listView;
}
}
I had the class also returning a simple List of type Name and Image that the CustomCell is waiting and nothing.
EDIT
public class TestObject
{
public string title { get; set; }
public string countries { get; set; }
}
void load()
{
List<TestObject> list = new List<TestObject>();
list.Add(new TestObject { title = "test1", countries = "esp,ita,prt" });
list.Add(new TestObject { title = "test2", countries = "esp,ita" });
list.Add(new TestObject { title = "test3", countries = "rus" });
var labelTitle = new Label()
{
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
VerticalOptions = LayoutOptions.StartAndExpand,
};
listdata = new ListView();
listdata.ItemsSource = list;
var cell = new DataTemplate(() => {
var grid = new Grid() { Padding = 8, RowSpacing = 5, ColumnSpacing = 5 };
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) });
labelTitle.SetBinding(Label.TextProperty, "title");
countriesLabel.SetBinding(Label.TextProperty, "countries"); //here i want to make a customcell to show the images, like be able to "bind" and calc the countries split the string by "," and add (name + ".png") then show the image.
// i was able to do it in a listview when i have the source in my side.. in this one i have to bind and then calc..
grid.Children.Add(labelTitle, 0, 0);
grid.Children.Add(countriesLabel, 1, 0);
});
listdata.ItemTemplate = cell;
}
for (int r = 0; r < m; r++)
{
TextBlock myTextBlockr = new TextBlock() { Text = "Text Block", Width = 350, Height = 40, FontSize = 20, VerticalAlignment = VerticalAlignment.Center, TextAlignment = TextAlignment.Center, HorizontalAlignment = HorizontalAlignment.Center };
string name = "TextBlock" + r.ToString();
myTextBlockr.Name = name;
ListBox list = new ListBox() { Height = 200, Width = 200 };
string k="list"+r;
list.Name = k;
}
I have created list box dynamically.I want to control its visibility in other function.I have used activator.createinstance method but it throws exception.
public void myTextBlock1_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
string name = ((TextBlock)sender).Name;
// name.Substring(10,9);
string strl = "list" + name.Substring(9);
object obj = Activator.CreateInstance(typeof(ListBox), strl);
ListBox list = (ListBox)obj;
list.Visibility = Visibility.Visible;
}
It throws following exception System.missingmethodexception .
Keep a reference to the ListBox in your class if you need to refer to it later. If you're creating multiple ListBoxes, add them to a Dictionary<string, ListBox> so you could look them up by a key later.
public class Demo {
private Dictionary<string, ListBox> _listboxes = new Dictionary<string, ListBox>();
private void CreateListBoxWithName(string name) {
var lb = new ListBox();
_listboxes.add(name, lb);
// do other stuff ...
}
private ListBox FindListBoxByName(string name) {
return _listboxes[name];
}
}
I want to change content of button1 on click event of button2 . But not able to get the object of grid's child Button class which is in List<> UiList.
Please Guide me in getting the right approach to look it and solve it . And also guide that if the object is build in runtime then how to access it ?
public partial class MainPage : PhoneApplicationPage
{
List<Grid> UIList = new List<Grid>();
Grid objGrid1 = null;
Button objButton1 = null;
Button objButton2 = null;
// Constructor
public MainPage()
{
InitializeComponent();
createGrid1("grid1");
createButton2("Button2");
}
public void createGrid1(string x)
{
objGrid1 = new Grid();
objGrid1.Height = 100;
objGrid1.Name = x;
objGrid1.Width = 200;
objGrid1.Margin = new Thickness(100, 100, 0, 0);
objGrid1.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
objGrid1.VerticalAlignment = System.Windows.VerticalAlignment.Top;
objGrid1.Background = new SolidColorBrush(Colors.Orange);
createButton1("changename");
}
public void createButton1(string _name)
{
objButton1 = new Button();
objButton1.Height = 90;
objButton1.Name = _name;
objButton1.Content="Button1";
objButton1.FontSize = 20;
objButton1.Width = 190;
objButton1.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
objButton1.VerticalAlignment = System.Windows.VerticalAlignment.Top;
objButton1.Background = new SolidColorBrush(Colors.Blue);
objButton1.Foreground = new SolidColorBrush(Colors.White);
objGrid1.Children.Add(objButton1);
LayoutRoot.Children.Add(objGrid1);
UIList.Add(objGrid1);
}
public void createButton2(string _name)
{
objButton2 = new Button();
objButton2.Margin = new Thickness(240, 300, 0, 0);
objButton2.Name = _name;
objButton2.Height = 90;
objButton2.Content = "Button2";
objButton2.FontSize = 20;
objButton2.Width = 190;
objButton2.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
objButton2.VerticalAlignment = System.Windows.VerticalAlignment.Top;
objButton2.Background = new SolidColorBrush(Colors.Blue);
objButton2.Foreground = new SolidColorBrush(Colors.White);
LayoutRoot.Children.Add(objButton2);
objButton2.Click += (s, e) =>
{
int c = UIList.ElementAt(0).Children.Count;
if (c == 1)
{
//logic to change content of Button1 on click of Button2
}
};
}
}
Assuming you cannot just keep a reference to the created control, such as in a class field, you can iterate through the Children property of the Grid and find the desired Button. If there are multiple buttons, you can differentiate them using the Tag property.
Once you find it, change the contents of the button using the Content property, as discussed in the contents above.