Custom Xamarin Cell Issue - mobile

I'm learning to use Xamarin, and was making a simple custom cell. However, when I run the app none of the information I set as the ListViews ItemsSource displays. I was wondering if there was an issue with the way I was binding the information or if it was an issue with the way I was constructing the custom cell.
Here is the cell class:
public class ButtonCell : ViewCell
{
#region Constructors
public ButtonCell()
{
//Button bg = new Button();
Label title = new Label()
{
TextColor = Color.Black,
FontSize = 12,
YAlign = TextAlignment.Start
};
Label description = new Label()
{
TextColor = Color.Black,
FontSize = 12,
YAlign = TextAlignment.End
};
title.SetBinding(Label.TextProperty, new Binding("Title"));
description.SetBinding(Label.TextProperty, new Binding("Budget"));
Grid labelLayout = new Grid()
{
/*VerticalOptions = LayoutOptions.Center,*/
Padding = new Thickness(5, 0, 5, 10),
Children =
{
title,
description
}
};
View = labelLayout;
/*Grid grid = new Grid()
{
Padding = new Thickness(5, 0, 5, 10),
Children =
{
bg,
labelLayout
}
};*/
}
#endregion
}
Here is the class that I want to display information from in the list view:
public class Bucket
{
#region Public Variables
public string Title;
public float Budget;
public BucketType Type;
public BucketCategory Category;
#endregion
#region Constructors
public Bucket()
{
Title = "";
Budget = 0;
Type = (BucketType)0;
Category = (BucketCategory)0;
}
public Bucket(string title, float budget, BucketType type, BucketCategory category)
{
Title = title;
Budget = budget;
Type = type;
Category = category;
}
#endregion
}
public enum BucketType
{
Flexible = 0,
Fixed
}
public enum BucketCategory
{
Bills = 0,
Food,
Hobbies
}
When I initialize the list view, it displays the appropriate number of cell. However, none of the information is display. Once again, I'm not sure if its a binding issue or maybe a formatting issue with the cell.
Thanks for your help in advance!

The following member variables in the Bucket class need changing to properties:
#region Public Variables
public string Title;
public float Budget;
public BucketType Type;
public BucketCategory Category;
#endregion
Needs changing to:
#region Public Variables
public string Title {get;set;};
public float Budget{get;set;};
public BucketType Type{get;set;};
public BucketCategory Category{get;set;};
#endregion
You also need to implement IPrpopertyChanged in order to make the bindings anything other than OneWay. I use a nugget package called Fody.PropertyChanged but the implementation is up to you.

Related

Exposing custom properties using UI Automation Framework

Given a very basic WinForms custom/user control, using System.Windows.Automation it is possible to manipulate built in properties for the custom control.
This is done like this:
public object GetPropertyValue(int propertyId)
{
if (propertyId == AutomationElementIdentifiers.NameProperty.Id)
{
return "Hello World!";
}
}
What I would like to do is expose custom properties to ui automation such as ReadyState, LastAccessed, Etc.
Is this possible?
No, you can't extend the list of properties, and this is complicated by the fact you use Winforms that has a poor UI Automation support (it uses IAccessible with bridges etc.).
What you can do though is add some fake objects to the automation tree, for example, here is a sample Winforms UserControl that does it:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
Button button = new Button();
button.Location = new Point(32, 28);
button.Size = new Size(75, 23);
button.Text = "MyButton";
Controls.Add(button);
Label label = new Label();
label.Location = new Point(49, 80);
label.Size = new Size(35, 13);
label.Text = "MyLabel";
Controls.Add(label);
MyCustomProp = "MyCustomValue";
}
public string MyCustomProp { get; set; }
protected override AccessibleObject CreateAccessibilityInstance()
{
return new UserControl1AccessibleObject(this);
}
protected class UserControl1AccessibleObject : ControlAccessibleObject
{
public UserControl1AccessibleObject(UserControl1 ownerControl)
: base(ownerControl)
{
}
public new UserControl1 Owner
{
get
{
return (UserControl1)base.Owner;
}
}
public override int GetChildCount()
{
return 1;
}
public override AccessibleObject GetChild(int index)
{
if (index == 0)
return new ValueAccessibleObject("MyCustomProp", Owner.MyCustomProp);
return base.GetChild(index);
}
}
}
public class ValueAccessibleObject : AccessibleObject
{
private string _name;
private string _value;
public ValueAccessibleObject(string name, string value)
{
_name = name;
_value = value;
}
public override AccessibleRole Role
{
get
{
return AccessibleRole.Text; // activate Value pattern
}
}
// note you need to override with member values, base value cannot always store something
public override string Value { get { return _value; } set { _value = value; } }
public override string Name { get { return _name; } }
}
And this is how it appears in the automation tree (using the inspect.exe tool):
Note this technique also supports writing back to the property because it's based on the ValuePattern.

how to create a custom DataGridViewComboBoxCell with floating label on it

I want to have two controls in the same datagridview column.
I want to customize the DataGridViewComboBoxCell so that it will show the values of the selected value and on it a floating label with some text. in the past i was able to do it with a checkbox and a label but the problem with the DataGridViewComboBoxCell is that it comes out with an empty datasource when I override the paint event.
I tried to assign the datasource again after I used the Paint event but then although I see values in the DataGridViewComboBoxCell and the label showing the right value, I get into an infinite loop so I see the GUI blinking constantly.
10x for the help.
the code is the following:
*when the form loads
MyDGVCheckBoxColumn col = new MyDGVCheckBoxColumn();
col.DataPropertyName = "value";
col.DataSource = list;
col.DisplayMember = "Yes";
col.ValueMember = "value";
col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
this.dataGridView1.Columns.Add(col);
this.dataGridView1.RowCount = 50;
the class for the generic list:
public class CheckThis
{
public string Yes { get; set; }
public string value { get; set; }
public CheckThis()
{
Yes = "gggg";
value = "1";
}
}
the code for the custom DataGridViewComboBoxCell (I used a similar example in the past from some site)
public class MyDGVCheckBoxColumn : DataGridViewComboBoxColumn
{
private string label;
public string Label
{
get
{
return label;
}
set
{
label = value;
}
}
public override DataGridViewCell CellTemplate
{
get
{
return new MyDGVCheckBoxCell();
}
}
}
public class MyDGVCheckBoxCell : DataGridViewComboBoxCell
{
private string label;
public string Label
{
get
{
return label;
}
set
{
label = value;
}
}
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{
// the base Paint implementation paints the check box
base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
// Get the check box bounds: they are the content bounds
Rectangle contentBounds = this.GetContentBounds(rowIndex);
// Compute the location where we want to paint the string.
Point stringLocation = new Point();
stringLocation.Y = cellBounds.Y + 30;
stringLocation.X = cellBounds.X + contentBounds.Bottom;
// Paint the string.
var res = false;
MyDGVCheckBoxColumn col = (MyDGVCheckBoxColumn)this.OwningColumn;
col.DataSource = list;
col.DisplayMember = "Yes";
col.ValueMember = "value";
this.label = "Customer Does Not Appear";
graphics.DrawString(
this.Label, new Font("Arial", 6, FontStyle.Bold), System.Drawing.Brushes.Red, stringLocation);
}
public object list { get; set; }
}

Provide a Collection as source to property in WPF Propertygrid

I have the following property of type string.
[Category("General")]
[DisplayName("Book Name")]
public string BookName
{ //getter;
//setter;
}
When binding an object containing this property to propertygrid, I would like to provide a list of type string as source.
List<string> booksource = new List<string>();
When Property is of type enum, it automatically populates combobox, I want to acheive same functionality through collection.
Edit:
Expanded:
enum BookType
{
Novel = 0,
Magazine = 1
}
class Class1
{
string _bookname = "Book 1";
BookType _booktype = BookType.Magazine;
[Category("General")]
[DisplayName("Book Name")]
public string BookName
{
get { return this._bookname; }
set { this._bookname = value; }
}
[Category("General")]
[DisplayName("Book Type")]
public BookType BookType
{
get { return this._booktype; }
set { this._booktype = value; }
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Class1 obj = new Class1();
this.wpfpropertygrid.SelectedObject = obj;
}
}
For the above code, the propertygrid displays a combobox with items "Magazine" and "Novel" for property BookType and a textbox with text "Book 1" for property BookName. I want the property BookName displayed as combobox to which i can explicitly provide a source. I would like to bind a list {"Book 1","Book 2","Book 3"} to property BookName, so that the user can select any one of them.
Better late than never ;-)
With PropertyGrid from Extended WPF Toolkit you can do this that way:
enum BookType
{
Novel = 0,
Magazine = 1
}
public class BookItemsSource : IItemsSource
{
public ItemCollection GetValues()
{
var books = new ItemCollection();
books.Add("Book 1");
books.Add("Book 2");
books.Add("Book 3");
return books;
}
}
public class Class1
{
string _bookname = "Book 1";
BookType _booktype = BookType.Magazine;
[Category("General")]
[DisplayName("Book Name")]
[ItemsSource(typeof(BookItemsSource))]
public string BookName
{
get { return this._bookname; }
set { this._bookname = value; }
}
[Category("General")]
[DisplayName("Book Type")]
public BookType BookType
{
get { return this._booktype; }
set { this._booktype = value; }
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Class1 obj = new Class1();
this.wpfpropertygrid.SelectedObject = obj;
}
}

WPF DataGrid - Can I decorate my POCOs with attributes to have custom column names?

I have a DataGrid in WPF and fill it with data like this:
public enum Sharing
{
Equal,
SurfaceBased,
}
public class Data
{
public bool Active { get; set; }
public string Name { get; set; }
public int Floor { get; set; }
public Sharing Sharing { get; set; }
}
public ObservableCollection<Data> _col = new ObservableCollection<Data>()
{
new Data(){Active = true, Name = "KRL", Floor = 0 },
new Data(){Name = "DAT", Floor = 1},
new Data(){Name = "TRE", Floor = 1},
new Data(){Name = "DUO", Floor = 2},
};
public MainWindow()
{
InitializeComponent();
grid.AutoGenerateColumns = true;
grid.DataContext = _col;
grid.ItemsSource = _col;
}
I was wondering if I could use some attributes on the enumerations and the POCO class so that the DataGrid displays them (instead of the variable names) on the headers and ComboCoxes.
Something like this:
public enum Sharing
{
[Name("This is a test")]
Equal,
[Name("This is a test 2")]
SurfaceBased,
}
Is this possible?
OK. Here is the way to do it for the Headers:
You add attributes, like Description attributes to your Properties.
public class MyPOCO
{
[Description("The amount you must pay")]
public float Amount { get; set; }
}
Then, in a class derived from DataGrid you do this:
protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
{
try
{
base.OnAutoGeneratingColumn(e);
var propDescr = e.PropertyDescriptor as System.ComponentModel.PropertyDescriptor;
e.Column.Header = propDescr.Description;
}
catch (Exception ex)
{
Utils.ReportException(ex);
}
}
For adding custom names to the members of the enumerations, you need to make a custom column. You can see a simple example here : https://stackoverflow.com/a/17510660/964053.

silver light datagrid

Iam new to silverlight so i need help from your side. my query is one page haivng the datagrid,that datagrid have only 6 columns.after 6 columns their is a scape so that scape showing itself one column.so i avoid that column in datagrid.scape may be show with out the column this is my query.
it is urgent for me.please resolve the solution as possible as early.
While I have no idea what a 'scape' is, what you need to do is start out by creating a 'display' class that inherits from IEditable and INotify. For example:
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace Application.Views.DisplayClasses
{
public class DisplayClass : IEditableObject, INotifyPropertyChanged
{
//Create private vars
private string a;
private string b;
private string c;
private string d;
private bool e;
// Create public properties with meta data to tell the grid to display and what order etc
[Display(AutoGenerateField = false)]
public string A
{
get { return a; }
set { a = value; }
}
[Display(Order = 0, Name = "B", AutoGenerateField = true)]
public string B
{
get { return b; }
set { b = value; }
}
[Display(Order = 1, Name = "C", AutoGenerateField = true)]
public String C
{
get { return c; }
set { c= value; }
}
[Display(Order = 2, Name = "D", AutoGenerateField = true)]
public string D
{
get { return d; }
set { d = value; }
}
[Display(Order = 2, Name = "E", AutoGenerateField = true)]
public string E
{
get { return e; }
set { e = value; }
}
#region IEditableObject Members
public void BeginEdit()
{
}
public void CancelEdit()
{
}
public void EndEdit()
{
}
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if ((propertyChanged != null))
{
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}
Then you need to create an ObservableCollection to store the data your getting back from the database in:
// Code to get data from the database (from your webservice)
//Make this Observable collection global
public static ObservableCollection<DisplayClass> ItemList = new ObservableCollection<DisplayClass>();
// In your oncompleted event method, put something similar to the following code
foreach (var DatabaseItem in DataFromMyWebService)
{
DisplayClass GridItem = new DisplayClass();
GridItem.A = DatabaseItem.A;
GridItem.B = DatabaseItem.B;
GridItem.C = DatabaseItem.C;
GridItem.D = DatabaseItem.D;
ItemList.Add(GridItem);
}
dgDataGrid.ItemsSource = ItemList;
You want to make your observable collection global so that if you need to change an item in your collection, the datagrid will automatically display those changes. Notice the meta data ([]) in the display class. That is how you control which properties are displayed and in what order. You will also want to set the property 'AutoGenerate="True"' in your datagrid element in your XAML code.

Resources