Binding data from ObservableCollection<User> to xaml page - silverlight-3.0

i am trying to bind the data from ObservableCollection to xaml page
pls let me know hoe to achive this
Xaml page
<UserControl.Resources>
<DataTemplate x:Key="User" >
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource User}}">
<data:DataGrid AutoGenerateColumns="True"
HeadersVisibility="All"
ItemsSource="{Binding }"
RowBackground="Cornsilk"
AlternatingRowBackground="BlanchedAlmond"
ColumnWidth="85" RowHeight="30"
IsReadOnly="True" CanUserResizeColumns="False">
</data:DataGrid>
</Grid>
.cs page
ObservableCollection<User> users;
public SLObservableCollectionSample()
{
InitializeComponent();
users = getUserCollection();
}
ObservableCollection<User> getUserCollection()
{
ObservableCollection<User> rVal = new ObservableCollection<User>();
rVal.Add(new User { Name = "Tom", Score = 2 });
rVal.Add(new User { Name = "Sam", Score = 3 });
rVal.Add(new User { Name = "John", Score = 4 });
rVal.Add(new User { Name = "Dave", Score = 5 });
rVal.Add(new User { Name = "Sue", Score = 1 });
return rVal;
}
#region User INotifyPropertyChanged
public class User : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set
{
if (value != name)
{
name = value;
onPropertyChanged(this, "Name");
}
}
}
private long score;
public long Score
{
get { return score; }
set
{
if (score != value)
{
score = value;
onPropertyChanged(this, "Score");
}
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void onPropertyChanged(object sender, string propertyName)
{
if (this.PropertyChanged != null)
{
PropertyChanged(sender, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
#endregion
Thanks
Prince

Related

Adding Searchview in Listview

I made an array to transfer the required data consisting of 3 elements(Heading,SubHeading, int ImageResourceId).
The data shows up well in listview but I couldn't do the research inside listview.
I want to do the research using searchview on specific SubHeading or both (Heading,SubHeading)
//on creat
listView.Adapter = new HomeScreenAdapter(this, HomeScreenAdapter.tableItems);
search.QueryTextChange += SearchV_QueryTextChange;
//filter listview
private void SearchV_QueryTextChange(object sender, SearchView.QueryTextChangeEventArgs e)
{
}
//
// 3-class listview item id
public class TableItem
{
public string Heading;
public string SubHeading;
public int ImageResourceId;
public TableItem(string Heading, string SubHeading, int ImageResourceId)
{
this.Heading = Heading;
this.SubHeading = SubHeading;
this.ImageResourceId = ImageResourceId;
}
}
}
//
//class adapter & array item
class HomeScreenAdapter : BaseAdapter<TableItem>
{
public static List<TableItem> tableItems = new List<TableItem>();
List<TableItem> items;
Activity context;
public void filldata()
{
tableItems.Add(new TableItem("hussein", "devepoer", Resource.Drawable.imaga));
tableItems.Add(new TableItem("ahmed", "admin", Resource.Drawable.imagb));
tableItems.Add(new TableItem("jasim", " manager", Resource.Drawable.imagc));
tableItems.Add(new TableItem("ahmed", "admin", Resource.Drawable.imagd));
tableItems.Add(new TableItem("jasim", " manager", Resource.Drawable.image));
tableItems.Add(new TableItem("jasim", " manager", Resource.Drawable.imagf));
}
}
According to your code, I do one sample by SubHeading to filter ListView data.
Firstly, create TableItem class:
public class TableItem
{
public string Heading { get; set; }
public string SubHeading { get; set; }
public int ImageResourceId { get; set; }
}
Then creating UI for ListView item:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ImageView android:id="#+id/imageView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
And create Adapter and filter for data:
public class TableItemAdapter : BaseAdapter<TableItem>, IFilterable
{
private List<TableItem> _originalData;
private List<TableItem> _items;
private readonly Activity _context;
public TableItemAdapter(Activity activity, IEnumerable<TableItem> tableitems)
{
_items = tableitems.OrderBy(s => s.SubHeading).ToList();
_context = activity;
Filter = new TableItemFilter(this);
}
public override TableItem this[int position]
{
get { return _items[position]; }
}
public Filter Filter { get; private set; }
public override int Count
{
get { return _items.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var view = convertView ?? _context.LayoutInflater.Inflate(Resource.Layout.TableItem, null);
var tableitem = _items[position];
var HeadingView = view.FindViewById<TextView>(Resource.Id.textView1);
var SubHeadingView = view.FindViewById<TextView>(Resource.Id.textView2);
var imageView = view.FindViewById<ImageView>(Resource.Id.imageView1);
HeadingView.Text = tableitem.Heading;
SubHeadingView.Text = tableitem.SubHeading;
imageView.SetImageResource(tableitem.ImageResourceId);
return view;
}
public override void NotifyDataSetChanged()
{
// If you are using cool stuff like sections
// remember to update the indices here!
base.NotifyDataSetChanged();
}
private class TableItemFilter : Filter
{
private readonly TableItemAdapter _adapter;
public TableItemFilter(TableItemAdapter adapter)
{
_adapter = adapter;
}
protected override FilterResults PerformFiltering(ICharSequence constraint)
{
var returnObj = new FilterResults();
var results = new List<TableItem>();
if (_adapter._originalData == null)
_adapter._originalData = _adapter._items;
if (constraint == null) return returnObj;
if (_adapter._originalData != null && _adapter._originalData.Any())
{
// Compare constraint to all names lowercased.
// It they are contained they are added to results.
results.AddRange(
_adapter._originalData.Where(
item => item.SubHeading.ToLower().Contains(constraint.ToString())));
}
// Nasty piece of .NET to Java wrapping, be careful with this!
returnObj.Values = FromArray(results.Select(r => r.ToJavaObject()).ToArray());
returnObj.Count = results.Count;
constraint.Dispose();
return returnObj;
}
protected override void PublishResults(ICharSequence constraint, FilterResults results)
{
using (var values = results.Values)
_adapter._items = values.ToArray<Java.Lang.Object>().Select(r =>r.ToNetObject<TableItem>()).ToList();
_adapter.NotifyDataSetChanged();
// Don't do this and see GREF counts rising
constraint.Dispose();
results.Dispose();
}
}
}
ObjectExtensions to implement filter:
public class JavaHolder : Java.Lang.Object
{
public readonly object Instance;
public JavaHolder(object instance)
{
Instance = instance;
}
}
public static class ObjectExtensions
{
public static TObject ToNetObject<TObject>(this Java.Lang.Object value)
{
if (value == null)
return default(TObject);
if (!(value is JavaHolder))
throw new InvalidOperationException("Unable to convert to .NET object. Only Java.Lang.Object created with .ToJavaObject() can be converted.");
TObject returnVal;
try { returnVal = (TObject)((JavaHolder)value).Instance; }
finally { value.Dispose(); }
return returnVal;
}
public static Java.Lang.Object ToJavaObject<TObject>(this TObject value)
{
if (Equals(value, default(TObject)) && !typeof(TObject).IsValueType)
return null;
var holder = new JavaHolder(value);
return holder;
}
}
Mainactivity.cs:
public class MainActivity : AppCompatActivity
{
private SearchView searchview1;
private ListView listview1;
private TableItemAdapter tableitemadapter;
private List<TableItem> tableitems;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
searchview1 = FindViewById<SearchView>(Resource.Id.searchView1);
listview1 = FindViewById<ListView>(Resource.Id.listView1);
tableitems = new List<TableItem>()
{
new TableItem(){Heading= "hussein", SubHeading="devepoer",ImageResourceId= Resource.Drawable.plu3 },
new TableItem(){Heading= "ahmed", SubHeading="admin",ImageResourceId= Resource.Drawable.plu3 },
new TableItem(){Heading= "jasim", SubHeading="manager",ImageResourceId= Resource.Drawable.plu3 },
new TableItem(){Heading= "cherry", SubHeading="admin",ImageResourceId= Resource.Drawable.plu3 },
new TableItem(){Heading= "barry", SubHeading="manager",ImageResourceId= Resource.Drawable.plu3 },
new TableItem(){Heading= "annine", SubHeading="manager",ImageResourceId= Resource.Drawable.plu3 }
};
tableitemadapter = new TableItemAdapter(this,tableitems);
listview1.Adapter = tableitemadapter;
searchview1.QueryTextChange += Searchview1_QueryTextChange;
}
private void Searchview1_QueryTextChange(object sender, SearchView.QueryTextChangeEventArgs e)
{
tableitemadapter.Filter.InvokeFilter(e.NewText);
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
The sample in github:
https://github.com/CherryBu/Searchviewsample
The screenshot:

How to highlight newly added row to Vaadin table in different color on click of a button?

I am new to Vaadin. How to highlight newly added row to Vaadin table in different color on click of a button? Below is the working code which is adding a new line to vaadin table on click of add button, but not highlighting in different colour. Here I have used DefaultFieldFactory to generate fields for each row.
public class ReviewTimesheetTable extends ViewComponent {
private Map<ReviewTimesheetTableDto, HashMap<String, AbstractField<?>>>
tableItem = new HashMap<ReviewTimesheetTableDto, HashMap<String,
AbstractField<?>>>();
BeanItemContainer<ReviewTimesheetTableDto> data = new
BeanItemContainer<ReviewTimesheetTableDto>(
ReviewTimesheetTableDto.class);
private Table table;
private Button btnAdd;
public void init() {
btnAdd = new Button();
btnAdd.setStyleName("link");
btnAdd.setIcon(new ThemeResource("images/addbtn.png"));
btnAdd.setDescription("Add Additional Task");
VerticalLayout layout = new VerticalLayout();
// Create a data source and bind it to a table
table = new Table("", data);
table.addStyleName("generateColumnTable");
table.setWidth("100%");
table.setPageLength(table.getItemIds().size());
table.setVisibleColumns(new Object[] { "chkBox", "taskDate", "employeeId", "taskId", "crJiraId",
"taskDesc","hour","minute"/*, "Delete" */});
table.setColumnHeader("chkBox", "Select");
table.setColumnHeader("taskDate", "Task Date");
table.setColumnHeader("employeeId", "Employee ID");
table.setColumnHeader("taskId", "Task ID");
table.setColumnHeader("crJiraId", "Subtask ID");
table.setColumnHeader("taskDesc", "Task Description");
table.setColumnHeader("hour", "Hour");
table.setColumnHeader("minute", "Minute");
table.setEditable(true);
table.setTableFieldFactory(new ImmediateFieldFactory());
table.setWidth("200%");
table.setPageLength(table.getItemIds().size());
HorizontalLayout btnLayout = new HorizontalLayout(table, btnAdd);
btnLayout.setWidth("100%");
btnLayout.setComponentAlignment(btnAdd, Alignment.TOP_RIGHT);
addListener();
layout.setMargin(true);
setCompositionRoot(btnLayout);
}
private void addListener() {
btnAdd.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
ReviewTimesheetTableDto tableDTO = new ReviewTimesheetTableDto(createdBy);
BeanItem<ReviewTimesheetTableDto> addItem = data.addItemAt(0,tableDTO);
}
});
}
public class ImmediateFieldFactory extends DefaultFieldFactory {
#Override
public Field<?> createField(Container container, Object itemId,
Object propertyId, Component uiContext) {
final ReviewTimesheetTableDto timesheetDetail = (ReviewTimesheetTableDto) itemId;
Map<String, AbstractField<?>> tableRow = null;
if(tableItem.get(timesheetDetail) == null)
{
tableItem.put(timesheetDetail,
new HashMap<String, AbstractField<?>>());
}
tableRow = tableItem.get(timesheetDetail);
if ("taskId".equals(propertyId)) {
GComboBox box = new GComboBox();
tableRow.put("taskId", box);
setTaskValues(box, timesheetDetail);
//addTaskListener(box);
box.setData(timesheetDetail);
if(timesheetDetail != null && timesheetDetail.getTaskId() != null) {
box.setDescription(timesheetDetail.getTaskId().getValue());
}
if(isSubmit){
box.setReadOnly(true);
}
if(timesheetDetail.getIsAdd() != null && timesheetDetail.getIsAdd()){
box.setReadOnly(false);
}
return box;
}else if ("crJiraId".equals(propertyId)) {
TextField field = new TextField();
field.setEnabled(true);
field.setWidth("200px");
field.setNullRepresentation("");
if(isSubmit){
field.setReadOnly(true);
}
if(timesheetDetail.getIsAdd() != null && timesheetDetail.getIsAdd()){
field.setReadOnly(false);
}
field.setMaxLength(50);
field.setDescription(timesheetDetail.getCrJiraId());
tableRow.put("crJiraId", field);
return field;
}else if ("taskDesc".equals(propertyId)) {
TextField field = new TextField();
field.setEnabled(true);
field.setWidth("300px");
field.setNullRepresentation("");
field.setReadOnly(false);
tableRow.put("taskDesc", field);
field.setMaxLength(2000);
field.setData(timesheetDetail);
addDetailPopupForTaskDesc(field, null);
if(timesheetDetail.getTaskDesc() != null){
field.setDescription(timesheetDetail.getTaskDesc());
}
field.setReadOnly(true);
if(timesheetDetail.getIsAdd() != null && timesheetDetail.getIsAdd()){
field.setReadOnly(false);
}
return field;
}else if ("hour".equals(propertyId)) {
GComboBox box = new GComboBox();
box.setWidth("60px");
tableRow.put("hour", box);
box.addValueChangeListener(addHourListener(box));
setHourValues(box, timesheetDetail);
box.setData(timesheetDetail);
if(isSubmit){
box.setReadOnly(true);
}
if(timesheetDetail.getIsAdd() != null && timesheetDetail.getIsAdd()){
box.setReadOnly(false);
}
return box;
}else if ("minute".equals(propertyId)) {
GComboBox box = new GComboBox();
box.setWidth("80px");
tableRow.put("minute", box);
box.addValueChangeListener(addMinuteListener(box));
setMinuteValues(box, timesheetDetail);
box.setData(timesheetDetail);
if(isSubmit){
box.setReadOnly(true);
}
if(timesheetDetail.getIsAdd() != null && timesheetDetail.getIsAdd()){
box.setReadOnly(false);
}
return box;
}else if ("employeeId".equals(propertyId)) {
/*TextField field = new TextField();
field.setEnabled(true);
field.setWidth("100%");
field.setNullRepresentation("");
field.setReadOnly(true);
field.setMaxLength(50);
field.setDescription(timesheetDetail.getEmpId());
tableRow.put("empId", field);
return field;*/
GComboBox box = new GComboBox();
tableRow.put("employeeId", box);
setEmpValues(box, timesheetDetail);
box.setData(timesheetDetail);
if(timesheetDetail != null && timesheetDetail.getEmployeeId() != null) {
box.setDescription(timesheetDetail.getEmployeeId().getValue());
}
if(isSubmit){
box.setReadOnly(true);
}
if(timesheetDetail.getIsAdd() != null && timesheetDetail.getIsAdd()){
box.setReadOnly(false);
}
/*if(timesheetDetail.getIsAdd() != null && timesheetDetail.getIsAdd()){
box.setReadOnly(false);
}*/
return box;
}else if ("taskDate".equals(propertyId)) {
DateField field = new DateField();
field.setEnabled(true);
field.setWidth("110px");
field.setReadOnly(true);
if(timesheetDetail.getIsAdd() != null && timesheetDetail.getIsAdd()){
field.setReadOnly(false);
}
field.setDateFormat("dd-MM-yyyy");
tableRow.put("taskDate", field);
return field;
}else if ("chkBox".equals(propertyId)) {
CheckBox field = new CheckBox();
field.setEnabled(true);
field.setWidth("30px");
field.setDescription(SHAConstants.SELECT);
tableRow.put("chkBox", field);
return field;
}else {
Field<?> field = super.createField(container, itemId,
propertyId, uiContext);
if (field instanceof TextField)
field.setWidth("100%");
field.setEnabled(true);
return field;
}
}
}
/*POJO (Bean)*/
import java.io.Serializable;
import java.util.Date;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.shaic.arch.fields.dto.SelectValue;
import com.shaic.arch.table.AbstractTableDTO;
import com.vaadin.data.util.BeanItemContainer;
public class ReviewTimesheetTableDto extends AbstractTableDTO implements Serializable {
#NotNull(message = "Please Select Task ID")
private SelectValue taskId;
#NotNull(message = "Please Enter Hours")
private SelectValue hour;
#NotNull(message = "Please Enter Minutes")
private SelectValue minute;
private BeanItemContainer<SelectValue> taskIdList;
private BeanItemContainer<SelectValue> hourList;
private BeanItemContainer<SelectValue> minuteList;
#NotNull(message = "Please Enter Sub Task")
#Size (min =1, message="Please Enter Sub Task")
private String crJiraId;
private String taskDesc;
#NotNull(message = "Please Enter Task Date")
private Date taskDate;
private Long key;
private Long hourValue;
private Long minuteValue;
private String createdBy;
//private String empId;
private Boolean chkBox;
#NotNull(message = "Please Select Employee ID")
private SelectValue employeeId;
public ReviewTimesheetTableDto() {
super();
// TODO Auto-generated constructor stub
}
public ReviewTimesheetTableDto(String createdBy) {
super();
this.createdBy = createdBy;
this.isAdd = Boolean.TRUE;
}
public ReviewTimesheetTableDto(Date taskDate, String userName, String createdBy) {
super();
this.taskDate = taskDate;
this.userName = userName;
this.isAdd = Boolean.TRUE;
this.createdBy = createdBy;
}
private Boolean isSubmit;
private Boolean isAdd;
private String userName;
public SelectValue getTaskId() {
return taskId;
}
public void setTaskId(SelectValue taskId) {
this.taskId = taskId;
}
public BeanItemContainer<SelectValue> getTaskIdList() {
return taskIdList;
}
public void setTaskIdList(BeanItemContainer<SelectValue> taskIdList) {
this.taskIdList = taskIdList;
}
public String getCrJiraId() {
return crJiraId;
}
public void setCrJiraId(String crJiraId) {
this.crJiraId = crJiraId;
}
public String getTaskDesc() {
return taskDesc;
}
public void setTaskDesc(String taskDesc) {
this.taskDesc = taskDesc;
}
public SelectValue getHour() {
return hour;
}
public void setHour(SelectValue hour) {
this.hour = hour;
}
public SelectValue getMinute() {
return minute;
}
public void setMinute(SelectValue minute) {
this.minute = minute;
}
public BeanItemContainer<SelectValue> getHourList() {
return hourList;
}
public void setHourList(BeanItemContainer<SelectValue> hourList) {
this.hourList = hourList;
}
public BeanItemContainer<SelectValue> getMinuteList() {
return minuteList;
}
public void setMinuteList(BeanItemContainer<SelectValue> minuteList) {
this.minuteList = minuteList;
}
public Long getKey() {
return key;
}
public void setKey(Long key) {
this.key = key;
}
public Long getHourValue() {
return hourValue;
}
public void setHourValue(Long hourValue) {
this.hourValue = hourValue;
}
public Long getMinuteValue() {
return minuteValue;
}
public void setMinuteValue(Long minuteValue) {
this.minuteValue = minuteValue;
}
public Boolean getIsSubmit() {
return isSubmit;
}
public void setIsSubmit(Boolean isSubmit) {
this.isSubmit = isSubmit;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getTaskDate() {
return taskDate;
}
public void setTaskDate(Date taskDate) {
this.taskDate = taskDate;
}
public Boolean getIsAdd() {
return isAdd;
}
public void setIsAdd(Boolean isAdd) {
this.isAdd = isAdd;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
/*public String getEmpId() {
return empId;
}
public void setEmpId(String empId) {
this.empId = empId;
}*/
public Boolean getChkBox() {
return chkBox;
}
public void setChkBox(Boolean chkBox) {
this.chkBox = chkBox;
}
public SelectValue getEmployeeId() {
return employeeId;
}
public void setEmployeeId(SelectValue employeeId) {
this.employeeId = employeeId;
}
}
Output of above code:
The easiest approach would be to use https://vaadin.com/api/7.7.13/com/vaadin/ui/Table.CellStyleGenerator.html to define conditional style name for the highlight. There are couple of options. If your item has date property which is set when updated, you could do comparison with that date and highlight rows that have been added in certain time frame, to indicate these are new. Alternatively you could have timer process clearing highlights after being added.

Xamarin Forms Maps Circle Custom Renderer

Experiencing two issues with a custom map/renderer on iOS.
Demo video: https://ufile.io/pscn3
I have a custom map class with a circle that is placed on the map.
A slider control resizes the circle from a bindable property.
When slider value changes, the circle's radius property gets updated with the selected value. But as you can see, it's not updating the radius on map, instead it moves the circle to new positions within a curve.
When the circle is moved outside x pixels, it disappears or gets cut off outside the visible bounds.
These are the classes being used:
Page.xaml:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:CompanyName.Data.ViewModels.MapWithCircleSlider;assembly=CompanyName"
xmlns:local="clr-namespace:CompanyName.UI;assembly=CompanyName"
x:Class="CompanyName.UI.Pages.MapWithCircleSlider"
Title="{Binding Title}">
<ContentPage.BindingContext>
<vm:MapWithCircleSliderViewModel></vm:MapWithCircleSliderViewModel>
</ContentPage.BindingContext>
<ContentPage.Content>
<ScrollView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<local:CircleMap Grid.Row="0" CircleRadius="{Binding CircleRadius}" Latitude="{Binding Latitude}" Longitude="{Binding Longitude}" MapRadius="{Binding MapRadius}" IsShowingUser="true" HasZoomEnabled="true" />
<!--<Image Grid.Row="0" HorizontalOptions="Center" VerticalOptions="Center" Source="ic_place_green_48dp.png" />-->
<StackLayout Grid.Row="1" Padding="32,16">
<Entry VerticalOptions="Start" Placeholder="navn *" Text="{Binding Name}">
<Entry.Style>
<OnPlatform x:TypeArguments="Style">
<On Platform="iOS" Value="{x:Static local:Styling.IosEntryStyle}" />
</OnPlatform>
</Entry.Style>
</Entry>
<Label VerticalOptions="Center" HorizontalOptions="Center" Text="{Binding CircleRadius, StringFormat='{0}m'}" />
<Slider VerticalOptions="End" Maximum="{Binding Maximum}" Minimum="{Binding Minimum}" Value="{Binding CircleRadius}" />
<!-- NB: Maximum must be set before Minimum, ref: https://bugzilla.xamarin.com/show_bug.cgi?id=23665 -->
</StackLayout>
</Grid>
</ScrollView>
</ContentPage.Content>
</ContentPage>
Pages ViewModel:
using System;
using CompanyName.ViewModels;
namespace CompanyName.Data.ViewModels.MapWithCircleSlider
{
public class MapWithCircleSliderViewModel : ViewModelBase
{
private string name;
private int circleRadius;
private float latitude;
private float longitude;
private int mapRadius;
public MapWithCircleSliderViewModel()
{
Name = "Labs";
CircleRadius = 200;
MapRadius = 200;
Latitude = 58.9698634f;
Longitude = 5.7331874f;
}
public int Maximum => 1000;
public int Minimum => 100;
public string Id { get; set; }
public bool IsEditMode { get; set; }
public string Title { get; set; }
public string Name
{
get => name;
set
{
if (name == value) return;
name = value;
OnPropertyChanged("Name");
}
}
public int CircleRadius
{
get => circleRadius;
set
{
if (circleRadius == value) return;
circleRadius = value;
OnPropertyChanged("CircleRadius");
}
}
public float Latitude
{
get => latitude;
set
{
if (Math.Abs(latitude - value) < float.Epsilon) return;
latitude = value;
OnPropertyChanged("Latitude");
}
}
public float Longitude
{
get => longitude;
set
{
if (Math.Abs(longitude - value) < float.Epsilon) return;
longitude = value;
OnPropertyChanged("Longitude");
}
}
public int MapRadius
{
get => mapRadius;
set
{
if (mapRadius == value) return;
mapRadius = value;
OnPropertyChanged("MapRadius");
}
}
}
}
CircleMap.cs
using System.Diagnostics;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
namespace CompanyName.UI
{
public class CircleMap : Map
{
private const int DefaultCircleRadius = 100;
private const float DefaultLatitude = 58.8523208f;
private const float DefaultLongitude = 5.7326743f;
private const int DefaultMapRadius = 150;
public static readonly BindableProperty CircleRadiusProperty = BindableProperty.Create("CircleRadius", typeof(int), typeof(CircleMap), DefaultCircleRadius, BindingMode.TwoWay, propertyChanged: OnCircleRadiusPropertyChanged);
public static readonly BindableProperty LatitudeProperty = BindableProperty.Create("Latitude", typeof(float), typeof(CircleMap), DefaultLatitude, BindingMode.TwoWay, propertyChanged: OnLatitudePropertyChanged);
public static readonly BindableProperty LongitudeProperty = BindableProperty.Create("Longitude", typeof(float), typeof(CircleMap), DefaultLongitude, BindingMode.TwoWay, propertyChanged: OnLongitudePropertyChanged);
public static readonly BindableProperty MapRadiusProperty = BindableProperty.Create("MapRadius", typeof(int), typeof(CircleMap), DefaultMapRadius, BindingMode.TwoWay, propertyChanged: OnMapRadiusPropertyChanged);
public CircleMap() : base(MapSpan.FromCenterAndRadius(new Position(DefaultLatitude, DefaultLongitude), Distance.FromMeters(DefaultMapRadius))) { }
public int CircleRadius
{
get => (int)GetValue(CircleRadiusProperty);
set => SetValue(CircleRadiusProperty, value);
}
public float Latitude
{
get => (float)GetValue(LatitudeProperty);
set => SetValue(LatitudeProperty, value);
}
public float Longitude
{
get => (float)GetValue(LongitudeProperty);
set => SetValue(LongitudeProperty, value);
}
public int MapRadius
{
get => (int)GetValue(MapRadiusProperty);
set => SetValue(MapRadiusProperty, value);
}
private static void OnCircleRadiusPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var circleMap = (CircleMap)bindable;
circleMap.CircleRadius = (int)newValue;
}
private static void OnLatitudePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var circleMap = (CircleMap)bindable;
circleMap.Latitude = (float)newValue;
MoveToRegion(circleMap);
}
private static void OnLongitudePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var circleMap = (CircleMap)bindable;
circleMap.Longitude = (float)newValue;
MoveToRegion(circleMap);
}
private static void OnMapRadiusPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var circleMap = (CircleMap)bindable;
circleMap.MapRadius = (int)newValue;
MoveToRegion(circleMap);
}
private static void MoveToRegion(CircleMap circleMap)
{
circleMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(circleMap.Latitude, circleMap.Longitude), Distance.FromMeters(circleMap.MapRadius)));
}
}
}
CustomMapRenderer.cs (iOS):
using CompanyName.UI;
using MapKit;
using ObjCRuntime;
using System;
using System.ComponentModel;
using System.Linq;
using Xamarin.Forms;
using Xamarin.Forms.Maps.iOS;
using Xamarin.Forms.Platform.iOS;
using CompanyName.iOS.Renderers.CustomRenderer;
using CompanyName.Utilities;
[assembly: ExportRenderer(typeof(CircleMap), typeof(CustomMapRenderer))]
namespace CompanyName.iOS.Renderers.CustomRenderer
{
/// <remarks>
/// https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/custom-renderer/map/circle-map-overlay/#Creating_the_Custom_Renderer_on_iOS
/// </remarks>
public class CustomMapRenderer : MapRenderer
{
private CircleMap circleMap;
private MKCircleRenderer circleRenderer;
private MKMapView NativeMap => Control as MKMapView;
protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
try
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
if (Control is MKMapView nativeMap)
{
nativeMap.RemoveOverlays(nativeMap.Overlays);
nativeMap.OverlayRenderer = null;
circleRenderer = null;
}
}
if (e.NewElement != null)
{
circleMap = (CircleMap)e.NewElement;
NativeMap.OverlayRenderer = GetOverlayRenderer;
AddOverlay();
}
}
catch (Exception ex)
{
//Logger.LogException(ex, GetType().Name);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (sender == null) return;
circleMap = (CircleMap)sender;
if (e.PropertyName == "VisibleRegion") OnVisibleRegionChanged();
if (e.PropertyName == CircleMap.CircleRadiusProperty.PropertyName) RedrawOverlay();
}
private MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper)
{
if (circleRenderer == null && !Equals(overlayWrapper, null))
{
var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as IMKOverlay;
circleRenderer = new MKCircleRenderer(overlay as MKCircle)
{
Alpha = 0.15f,
FillColor = CompanyName.Constants.Colors.Skobeloff500.ToUIColor(),
LineWidth = 1,
StrokeColor = CompanyName.Constants.Colors.Skobeloff500.ToUIColor()
};
}
return circleRenderer;
}
private void OnVisibleRegionChanged()
{
SetNewCoordinates();
RedrawOverlay();
}
private void SetNewCoordinates()
{
circleMap.Latitude = (float)circleMap.VisibleRegion.Center.Latitude;
circleMap.Longitude = (float)circleMap.VisibleRegion.Center.Longitude;
circleMap.MapRadius = (int)circleMap.VisibleRegion.Radius.Meters;
}
private void RedrawOverlay()
{
RemoveOverlays();
AddOverlay();
}
private void RemoveOverlays()
{
if (NativeMap?.Overlays == null) return;
if (NativeMap.Overlays.Any()) NativeMap.RemoveOverlays(NativeMap.Overlays);
}
private void AddOverlay()
{
var circleOverlay = MKCircle.Circle(new CoreLocation.CLLocationCoordinate2D(circleMap.Latitude, circleMap.Longitude), circleMap.CircleRadius);
NativeMap.AddOverlay(circleOverlay);
}
}
}
Any feedback / suggestions are highly appreciated!
You can try to refresh the circleRenderer to achieve your effect like:
private void RemoveOverlays()
{
if (NativeMap?.Overlays == null) return;
if (NativeMap.Overlays.Any())
{
NativeMap.RemoveOverlays(NativeMap.Overlays);
circleRenderer = null;
NativeMap.OverlayRenderer = GetOverlayRenderer;
}
}

DataBinding 2 ComboBoxes wpf

I need to build a form where I have 2 comboBoxes .
Select country and you get the cities of that country.
I m new to wpf so help me as I not sure what I am missing.
At the moment It doesnt even populate it.
Any help suggestions really appreaciated!
This is what I have done:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var window = new MainWindow();
var countryCitymodel = new CountryCityModel();
var repository = new CountryCityRepository();
var viewModel = new CountryCityViewModel(countryCitymodel, repository);
window.Show();
}
}
MainWindow xaml
<Window x:Class="WpfDatabinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:view="clr-namespace:WpfDatabinding.Views"
Title="MainWindow" Height="350" Width="525">
<Grid>
<view:CountryCityView />
</Grid>
</Window>
CountryCityView xaml
<UserControl x:Class="WpfDatabinding.Views.CountryCityView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="75" d:DesignWidth="300">
<Grid Height="64" Width="291">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="97"/>
<ColumnDefinition Width="13" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Countries" Margin="-6,6,5,0" Grid.ColumnSpan="2" Height="33"></Label>
<Label Grid.Row="1" Content="Cities" Grid.ColumnSpan="2"></Label>
<ComboBox Name="cboCountries"
ItemsSource="{Binding Path=Countries}"
SelectedValuePath="Name"
DisplayMemberPath="{Binding Name}"
Grid.Column="2"
Margin="0,10"></ComboBox>
<ComboBox Name="cboCities"
Grid.Column="2"
Grid.Row="1"
ItemsSource="{Binding Path=Cities}" Height="20" Margin="0,0,0,1">
</ComboBox>
</Grid>
</UserControl>
CountryCityView
public partial class CountyrCityView:UserControl
{
public CountryCityView()
{
InitializeComponents();
}
public CountryCityView(CountryCityViewModel countryCityViewModel)
{
InitializeComponents();
DataContext=countryCityViewModel;
}
}
CountryCityViewModel
public class CountryCityViewModel : ViewModelBase
{
private readonly CountryCityModel _countryCityModel;
readonly CountryCityRepository _repository;
RelayCommand _getCountriesCommand;
private RelayCommand _getCitiesCommand;
public CountryCityViewModel(CountryCityModel countryCityModel, CountryCityRepository repository)
{
_countryCityModel = countryCityModel;
_repository = repository;
GetCountries.Execute(null);
}
public List<Country> Countries
{
get { return _countryCityModel.Countries; }
set
{
_countryCityModel.Countries = value;
OnPropertyChanged("Countries");
}
}
public List<City> Cities
{
get { return _countryCityModel.Cities; }
set
{
_countryCityModel.Cities = value;
OnPropertyChanged("Cities");
}
}
public Country SelectedCountry
{
get { return _countryCityModel.SelectedCountry; }
set
{
_countryCityModel.SelectedCountry = value;
OnPropertyChanged("SelectedCountry");
}
}
public City SelectedCity
{
get { return _countryCityModel.SelectedCity; }
set
{
_countryCityModel.SelectedCity = value;
OnPropertyChanged("SelectedCity");
}
}
public ICommand GetCountries
{
get
{
if (_getCountriesCommand == null)
{
_getCountriesCommand = new RelayCommand(param => GetCountryList(), param => CanGetCountries());
}
return _getCountriesCommand;
}
}
public ICommand GetCities
{
get
{
if (_getCitiesCommand == null)
{
_getCitiesCommand = new RelayCommand(param => GetCityList(), param => CanGetCities());
}
return _getCitiesCommand;
}
}
private List<Country> GetCountryList()
{
Countries = _repository.GetCountries();
return Countries;
}
private static bool CanGetCountries()
{
return true;
}
private List<City> GetCityList()
{
Cities = _repository.GetCities(SelectedCountry.Name);
return Cities;
}
private static bool CanGetCities()
{
return true;
}
}
Model
public class CountryCityModel
{
public List<Country> Countries { get; set; }
public List<City> Cities { get; set; }
public Country SelectedCountry{ get; set; }
public City SelectedCity { get; set; }
}
Types
public class City
{
public string Name { get; set; }
public string CountryName { get; set; }
}
public class Country
{
public string Name { get; set; }
}
Repository
public List<Country>GetCountries()
{
return new List<Country>
{
new Country{Name = "Italy"},
new Country{Name = "Germany"},
new Country{Name = "France"},
new Country{Name = "England"}
};
}
public List<City> GetCities(string countryName)
{
return Cities().Where(c => c.CountryName == countryName).ToList();
}
private static IEnumerable<City> Cities()
{
return new List<City>
{
new City { CountryName="Italy",Name = "Rome"},
new City {CountryName="France",Name = "Paris"},
new City{CountryName="Germany",Name ="Berlin"},
new City{CountryName="England",Name ="London"}
};
}
}
Are you setting the data context of the view to your ViewModel somewhere? I don't see that in the code listed above.
e.g.
var viewModel = new CountryCityViewModel(countryCitymodel, repository);
window.DataContext = viewModel;

WPF - Binding to CheckBox not working in a HierarchicalDataTemplate

In a WPF treeview I am trying to automatically check the children if the parent node is being checked. I am using a view model for that and a bindable object for the nodes, however all my attempts failed. Here is the code (C# + XAML). Any ideas would be greatly appreciated
<Window x:Class="TestCheckBoxBinding.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestCheckBoxBinding"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True"/>
</Style>
<HierarchicalDataTemplate DataType="{x:Type local:TestCategory}" ItemsSource="{Binding Tests, Mode=OneTime}">
<Label Content="{Binding Name}"></Label>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Test}" ItemsSource="{Binding Children, Mode=OneTime}">
<StackPanel Orientation="Horizontal">
<CheckBox VerticalAlignment="Center" IsChecked="{Binding IsChecked, Mode=TwoWay}"></CheckBox>
<Label Content="{Binding Name}"></Label>
</StackPanel>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView ItemsSource="{Binding Categories, Mode=OneTime}"></TreeView>
</Grid>
public class TestsViewModel
{
public static void PopulateList(TestsViewModel vm)
{
TestCategory cat1 = new TestCategory() { Id = 1, Name = "First category" };
Test t1 = new Test() { Name = "Test1" };
Test t2 = new Test() { Name = "Test2" };
Test t3 = new Test() { Name = "Test3" };
t1.AddChild(t2);
t1.AddChild(t3);
Test t4 = new Test() { Name = "Test4" };
cat1.AddTest(t1);
cat1.AddTest(t4);
vm.AddTestCategory(cat1);
TestCategory cat2 = new TestCategory() { Id = 2, Name = "Second category" };
Test t5 = new Test() { Name = "Test1" };
Test t6 = new Test() { Name = "Test2" };
Test t7 = new Test() { Name = "Test3" };
t6.AddChild(t7);
Test t8 = new Test() { Name = "Test4" };
cat2.AddTest(t5);
cat2.AddTest(t6);
cat2.AddTest(t8);
vm.AddTestCategory(cat2);
}
private readonly IEnumerable<TestCategory> categories = new List<TestCategory>();
public IEnumerable<TestCategory> Categories { get { return categories; } }
public void AddTestCategory(TestCategory testCategory)
{
((IList<TestCategory>)categories).Add(testCategory);
}
}
public class TestCategory
{
public int Id { get; set; }
public string Name { get; set; }
private readonly IEnumerable<Test> tests = new List<Test>();
public IEnumerable<Test> Tests { get { return tests; } }
public void AddTest(Test t)
{
((IList<Test>)tests).Add(t);
}
}
public class Test : INotifyPropertyChanged
{
private string name;
public string Name
{
set
{
if (name != value)
{
name = value;
this.OnPropertyChanged("Name");
}
}
get { return name; }
}
public bool? isChecked = false;
public bool? IsChecked
{
get { return isChecked; }
set
{
if (isChecked != value)
{
isChecked = value;
if (children.Count() > 0)
{
foreach (var test in children)
{
test.isChecked = value;
test.Name += ".";
}
}
this.OnPropertyChanged("IsChecked");
}
}
}
public void AddChild(Test test)
{
((IList<Test>)children).Add(test);
}
private readonly IEnumerable<Test> children = new List<Test>();
public IEnumerable<Test> Children
{
get { return children; }
}
#region INotifyPropertyChanged Members
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string propName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
Oups, child checkboxes are not being checked because I wasn't setting their IsChecked property. I was setting the isChecked field, which bypasses the property setter and prevents PropertyChanged from being raised.

Resources