Xamarin Forms Master Detail Page Icon, and Menu Icon - master-detail

I'm following the instructions here;
https://www.syntaxismyui.com/xamarin-forms-masterdetail-page-navigation-recipe/
The navigation bar icon is placed too far to the right by default. Is there a way to center it on the navigation bar? The hamburger menu icon is also pushed far to the right.
EDIT: I added a picture for an example of what I have. Funny thing, in another app the icon is all the way to the left.
EDIT:
Here's the code:
public class RootPage : MasterDetailPage
{
MenuPage menuPage;
public RootPage()
{
menuPage = new MenuPage();
menuPage.Menu.ItemSelected += (sender, e) => NavigateTo(e.SelectedItem as MenuItem);
Master = menuPage;
NavigationPage page = new NavigationPage(new Home());
page.BarBackgroundColor = Color.FromHex("#56198E");
Detail = page;
}
void NavigateTo(MenuItem menu)
{
if (menu == null)
return;
Page displayPage = (Page)Activator.CreateInstance(menu.TargetType);
NavigationPage page = new NavigationPage(displayPage);
page.BarBackgroundColor = Color.FromHex("#56198E");
Detail = page;
menuPage.Menu.SelectedItem = null;
IsPresented = false;
}
}
public class MenuPage : ContentPage
{
public ListView Menu { get; set; }
public MenuPage()
{
Icon = "settings.png";
Title = "menu"; // The Title property must be set.
BackgroundColor = Color.FromHex("#56198E");
Menu = new MenuListView();
var menuLabel = new ContentView
{
Padding = new Thickness(10, 36, 0, 5),
Content = new Label
{
TextColor = Color.FromHex("#C8C8C8"),
Text = "MENU",
}
};
var layout = new StackLayout
{
Spacing = 0,
VerticalOptions = LayoutOptions.FillAndExpand
};
layout.Children.Add(menuLabel);
layout.Children.Add(Menu);
Content = layout;
}
}
public class MenuListView : ListView
{
public MenuListView()
{
List<MenuItem> data = new MenuListData();
ItemsSource = data;
VerticalOptions = LayoutOptions.FillAndExpand;
BackgroundColor = Color.Transparent;
// SeparatorVisibility = SeparatorVisibility.None;
var cell = new DataTemplate(typeof(MenuCell));
cell.SetBinding(MenuCell.TextProperty, "Title");
cell.SetBinding(MenuCell.ImageSourceProperty, "IconSource");
ItemTemplate = cell;
}
}
public class MenuListData : List<MenuItem>
{
public MenuListData()
{
this.Add(new MenuItem()
{
Title = " Home",
IconSource = "Home.png",
TargetType = typeof(Home)
});
this.Add(new MenuItem()
{
Title = " Register for Classes",
IconSource = "Calendar.png",
TargetType = typeof(Register)
});
this.Add(new MenuItem()
{
Title = " Search Instructors",
IconSource = "ContactsSearch.png",
TargetType = typeof(SearchInstructors)
});
}
}
public class MenuItem
{
public string Title { get; set; }
public string IconSource { get; set; }
public Type TargetType { get; set; }
}

I would recommend trying different icon sizes. I was having some issues myself when the image was too large. In my tests I was originally using a 144x144 image and it worked correctly most of the time. When I attempted a 700x700 pixel image it was dead center and I would lose my title.
Screen Resolution - 768x1280
App Icon
144x144 - Slightly away from flush next to the Menu Icon
700x700 - Center
Menu Icon -44x44 (and always flush to the left)

Related

Access treeviewitem from HierarchicalDataTemplate in WPF

I am trying to access the treeviewitem created using HierarchicalDataTemplate based on the Name of the header. Also i want to access the control inside (in this case rectangle) the treeviewitem and change its color. I tried many ways but no success. Below is my code. I am generating Treeview using custom class and xml.
public partial class Window1 : Window
{
ObservableCollection<Step> TreeViewTemplate;
public Window1()
{
TreeViewTemplate = new ObservableCollection<Step>();
InitializeComponent();
SetDataTemplate("NEWSITECOPPER_PROPOSAL", "Proposal");
tvMain.ItemsSource = TreeViewTemplate;
getTreeViewItem();
}
private void getTreeViewItem()
{
TreeViewItem item = (TreeViewItem)(tvMain.ItemContainerGenerator.ContainerFromItem(tvMain.Items[3]));
}
private void SetDataTemplate(string ProcessName, string journeyName)
{
try
{
TreeViewTemplate.Clear();
//XDocument xDoc = XDocument.Load(#"C:\Users\606347769\Desktop\Hemil\Others\TreeView\TreeView\Data.xml");
XDocument xDoc = XDocument.Load(#"C:\Users\606347769\Documents\Visual Studio 2008\Projects\TestAPplication\WpfApplication1\ProcessJourneyCriteria.xml");
var JourneySteps = xDoc.Elements("ProcessAreas").Elements("Process").Where(x =>
x.Attribute("name").Value == ProcessName).Select(y =>
y.Elements("Journey").Where(k => k.Attribute("name").Value == journeyName));
var FinalSteps = JourneySteps.FirstOrDefault();
FinalSteps.Elements("Step").ToList<XElement>().ForEach(x =>
{
string key = x.Attribute("name").Value;
ObservableCollection<ChildStep> value = new ObservableCollection<ChildStep>();
x.Elements("ChildStep").ToList<XElement>().ForEach(y =>
{
ObservableCollection<GrandChildStep> GC = new ObservableCollection<GrandChildStep>();
y.Elements("GrandChildStep").ToList<XElement>().ForEach(k =>
{
GC.Add(new GrandChildStep { Name = k.Attribute("name").Value });
});
value.Add(new ChildStep { Name = y.Attribute("name").Value, GrandChildStep = GC });
});
TreeViewTemplate.Add(new Step { Name = key, ChildStep = value });
});
}
catch (Exception)
{
}
}
}
Below is the custom class i have created
class Step
{
public string Name { get; set; }
public System.Collections.ObjectModel.ObservableCollection<ChildStep> ChildStep { get; set; }
}
class ChildStep
{
public string Name { get; set; }
public System.Collections.ObjectModel.ObservableCollection<GrandChildStep> GrandChildStep { get; set; }
}
class GrandChildStep
{
public string Name { get; set; }
}
You should expose everything you want to access on your (view) model and just bind to it, like the Background of the shape or the IsSelected property of the item (needs to be bound in ItemContainerStyle).
If you need to "access UI controls" in WPF you are usually doing something wrong.
name the child,for eg. in your case x:Name="Rect" to Rectangle
then
Declare this helper method in your Code
T GetVisualChild<t>(DependencyObject parent, string name) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<t>(v, name);
}
if (child != null)
{
break;
}
}
return child;
}
then
just declare Rectangle Rect=new Rectangle(); in constructor or loaded event.
and when you want to access the child. use that declared helper method. for eg.
Rect=GetVisualChild<treeview>(this, "Rect")
Note: here "treeview" is the name of parent You may give the name of parent accessing the child directly.

How to bind a combo box datasource to a form/listbox in windows forms?

I would like to get the form as datasource when i click combo box. How could i achieve this. Please give suggestion.
I've created a PopupComboBox class which inherits from the standard Windows Forms ComboBox. It has a Title property that you can set which will be used on the popup window when the combo is clicked.
public class PopupComboBox : ComboBox
{
private string title;
public string Title
{
get { return this.title; }
set { this.title = value; }
}
public PopupComboBox() : base()
{
}
public PopupComboBox (string title)
: base()
{
this.title = title;
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
// Show the popup form
var popup = new SelectItemForm(this.title, this);
var result = popup.ShowDialog(this);
if (result == DialogResult.OK)
{
// Select this item in the ComboBox
SelectedIndex = this.FindStringExact(popup.SelectedDisplay);
}
}
}
When you click on the combo, a popup form will come up (source code below for SelectItemForm). It uses the DataSource, ValueMember and DisplayMember of the parent PopupComboBox to populate a ListView with the list of items from the combo. When you click on OK, it will save the selected item in the SelectedValue and SelectedDisplay properties so that we can select that item in the ComboBox when the form closes.
public partial class SelectItemForm : Form
{
public object SelectedValue { get; private set; }
public string SelectedDisplay { get; private set; }
public SelectItemForm(string title, PopupComboBox parent)
:base()
{
InitializeComponent();
this.Text = title;
// Add items to the list
foreach (var item in parent.Items)
{
// Get the display and value member properties for this combo box
// and use them for the Code/Name columns in the popup form
var props = item.GetType().GetProperties();
var code = props.Where(p => p.Name == parent.ValueMember).Single().GetValue(item);
var name = props.Where(p => p.Name == parent.DisplayMember).Single().GetValue(item);
listView.Items.Add(new ListViewItem(
new string[] { code.ToString(), name.ToString() }));
}
}
private void btnOk_Click(object sender, EventArgs e)
{
if (listView.SelectedItems != null && listView.SelectedItems.Count > 0)
{
SelectedValue = listView.SelectedItems[0].Text;
SelectedDisplay = listView.SelectedItems[0].SubItems[1].Text;
DialogResult = DialogResult.OK;
}
else
{
MessageBox.Show(this, "Select an item first", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
}
}
Here is the designer part of the form, where you can see what properties I've changed for the ListView to look like it does:
partial class SelectItemForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.listView = new System.Windows.Forms.ListView();
this.btnOk = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.Code = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.Value = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.SuspendLayout();
//
// listView
//
this.listView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.listView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.Code,
this.Value});
this.listView.FullRowSelect = true;
this.listView.GridLines = true;
this.listView.Location = new System.Drawing.Point(3, 3);
this.listView.MultiSelect = false;
this.listView.Name = "listView";
this.listView.Size = new System.Drawing.Size(432, 170);
this.listView.TabIndex = 0;
this.listView.UseCompatibleStateImageBehavior = false;
this.listView.View = System.Windows.Forms.View.Details;
//
// btnOk
//
this.btnOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnOk.Location = new System.Drawing.Point(272, 179);
this.btnOk.Name = "btnOk";
this.btnOk.Size = new System.Drawing.Size(75, 23);
this.btnOk.TabIndex = 1;
this.btnOk.Text = "OK";
this.btnOk.UseVisualStyleBackColor = true;
this.btnOk.Click += new System.EventHandler(this.btnOk_Click);
//
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.Location = new System.Drawing.Point(353, 179);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 2;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// Code
//
this.Code.Text = "Code";
this.Code.Width = 108;
//
// Value
//
this.Value.Text = "Name";
this.Value.Width = 296;
//
// SelectItemForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(440, 214);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnOk);
this.Controls.Add(this.listView);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "SelectItemForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Title";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ListView listView;
private System.Windows.Forms.Button btnOk;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.ColumnHeader Code;
private System.Windows.Forms.ColumnHeader Value;
}
I've also created a small test form where you can test out the functionality of the PopupComboBox, using a small list of products. You'll need to add a PopupComboBox to the form in the designer, and call it comboPopup.
public partial class TestForm : Form
{
public class Product
{
public string Code { get; set; }
public string Name { get; set; }
}
public TestForm()
{
InitializeComponent();
}
private void TestForm_Load(object sender, EventArgs e)
{
var products = new List<Product>();
products.Add(new Product { Code = "0001", Name = "Coca Cola" });
products.Add(new Product { Code = "0002", Name = "Mountain Dew" });
products.Add(new Product { Code = "0003", Name = "Sprite Zero" });
comboPopup.DataSource = products;
comboPopup.DisplayMember = "Name";
comboPopup.ValueMember = "Code";
}
}

JavaFX 8: ComboBox button cell update behavior

I have a combo box which contains items of type Dog. If all items are replaced with new ones (via setAll on the ObservableList model) , the item renderer can cope with this update, while the button cell renderer cannot:
Here's a minimal example to reproduce the problem (full source incl. imports on GitHub):
public class ComboBoxRefresh extends Application {
private static final class Dog {
private final String name;
public Dog(String name) {
this.name = name;
}
}
private static final class DogListCell extends ListCell<Dog> {
#Override
public void updateItem(Dog item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText("");
} else {
setText(item.name);
}
}
}
private static List<Dog> createThreeDogs() {
return range(0, 3).mapToObj(i -> new Dog("Buddy " + i)).collect(toList());
}
#Override
public void start(Stage stage) throws Exception {
ObservableList<Dog> items = observableArrayList(createThreeDogs());
ComboBox<Dog> comboBox = new ComboBox<>(items);
comboBox.setPrefWidth(400);
comboBox.setCellFactory(listView -> new DogListCell());
comboBox.setButtonCell(new DogListCell());
Button button = new Button("Refresh");
button.setOnAction(event -> {
List<Dog> newItems = createThreeDogs();
items.setAll(newItems);
});
VBox box = new VBox(10, comboBox, button);
box.setPadding(new Insets(10));
Scene scene = new Scene(box);
stage.setScene(scene);
stage.show();
}
}
If I add an equals implementation to the Dog class, everything works, but this is not an option in my real application.
Are there any work-arounds to enforce a proper refresh of the button cell?
It seems to be a bug. Workaround could be
button.setOnAction( event -> {
List<Dog> newItems = createThreeDogs();
items.clear();
items.addAll(newItems);
} );

Xamarin.Forms - Detect orientation & adjust page

I'd like to know the orientation of the device (Android, iOS & Windows Phone) at the time I'm building up my page. The page is having a grid with 3 columndefinitions and should have 5 columndefinitions as soon as the orientation got changed to landscape.
Grid grid = new Grid
{
HorizontalOptions = LayoutOptions.Fill,
VerticalOptions = LayoutOptions.Fill,
RowSpacing = 15,
ColumnSpacing = 15,
Padding = new Thickness(15),
ColumnDefinitions =
{
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
}
};
for (int i = 0; i < 12; i++)
{
Image img = new Image()
{
Source = "ButtonBlue.png"
};
//if(DependencyService.Get<IDeviceInfo>().IsPortraitOriented())
//{
grid.Children.Add(img, i % 3, i / 3);
//}
//else
//{
// grid.Children.Add(button, i % 5, i / 5);
//}
}
this.Content = new ScrollView
{
Orientation = ScrollOrientation.Vertical,
Content = grid
};
So here I added 12 images to test my code. The page is looking good in portrait-orientation and is having a lot of space between columns if the device is in landscape-orientation.
I'm also trying to use dependency injection to retrieve the information. The DependencyService is doing his job, but I don't have any success retrieving the orientation of the device...
In xamarin.forms, you can get notification from android part by using MessageCenter.
1.In Shared Project
public partial class MyPage : ContentPage
{
public MyPage ()
{
InitializeComponent ();
Stack = new StackLayout
{
Orientation = StackOrientation.Vertical,
};
Stack.Children.Add (new Button { Text = "one" });
Stack.Children.Add (new Button { Text = "two" });
Stack.Children.Add (new Button { Text = "three" });
Content = Stack;
MessagingCenter.Subscribe<MyPage> (this, "Vertical", (sender) =>
{
this.Stack.Orientation = StackOrientation.Vertical;
this.ForceLayout();
});
MessagingCenter.Subscribe<MyPage> (this, "Horizontal", (sender) =>
{
this.Stack.Orientation = StackOrientation.Horizontal;
this.ForceLayout();
});
}
public StackLayout Stack;
}
2.In Android Project
[Activity (Label = "XamFormOrientation.Android.Android", MainLauncher = true, ConfigurationChanges = global::Android.Content.PM.ConfigChanges.Orientation | global::Android.Content.PM.ConfigChanges.ScreenSize)]
public class MainActivity : AndroidActivity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
Xamarin.Forms.Forms.Init (this, bundle);
SetPage (App.GetMainPage ());
}
public override void OnConfigurationChanged (global::Android.Content.Res.Configuration newConfig)
{
base.OnConfigurationChanged (newConfig);
if (newConfig.Orientation == global::Android.Content.Res.Orientation.Portrait) {
MessagingCenter.Send<MyPage> (null, "Vertical");
} else if (newConfig.Orientation == global::Android.Content.Res.Orientation.Landscape) {
MessagingCenter.Send<MyPage> (null, "Horizontal");
}
}
}
I solved a similar problem and find it on great post which maybe helpfull for you (see hyperlink below).
In shortcut : Find out orientation by
Page.Width < Page.Height
and use this information in constructor of ContentPage (or other) when creating page
http://www.sellsbrothers.com/Posts/Details/13740

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; }
}

Resources