I have two separate Silverlight usercontrols containing grids and i want these to share a set of columndefinitions. The columndefinitions must be created dynamically. How can i do this?
You can just add them in code if that is sufficient:
private void CreateColumnDefinitions(Grid grid)
{
grid.ColumnDefinitions.Add(
new ColumnDefinition() { Width = new GridLength(10, GridUnitType.Star) });
grid.ColumnDefinitions.Add(
new ColumnDefinition() { Width = new GridLength(5, GridUnitType.Star) });
grid.ColumnDefinitions.Add(
new ColumnDefinition() { Width = new GridLength(5, GridUnitType.Star) });
}
Related
I have a project. I have a table. ( Made from grid ) And i have a entry/Textbox. I need make like customer will write number to entry ( Lets call that number "n" ). Then i need add n row inside of my table made from grid. How can i do that ?
Its my codes for make grid table.
gr.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(1, GridUnitType.Absolute)
});
gr.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(1, GridUnitType.Star)
});
gr.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(1, GridUnitType.Absolute)
});
gr.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(1, GridUnitType.Star)
});
gr.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(1, GridUnitType.Absolute)
});
gr.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(1, GridUnitType.Star)
});
gr.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(1, GridUnitType.Absolute)
});
gr.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(1, GridUnitType.Star)
});
gr.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(1, GridUnitType.Absolute)
});
gr.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(1, GridUnitType.Absolute)
});
gr.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(1, GridUnitType.Star)
});
gr.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(1, GridUnitType.Absolute)
});
gr.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(1, GridUnitType.Star)
});
gr.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(1, GridUnitType.Absolute)
});
var backgroundbox = new BoxView
{
Color = System.Drawing.Color.FromArgb(-32513)
};
gr.Children.Add(backgroundbox, 0, 1);
Grid.SetColumnSpan(backgroundbox, 5);
var ustyatay = new BoxView { Color = System.Drawing.Color.Gray };
gr.Children.Add(ustyatay, 0, 0);
Grid.SetColumnSpan(ustyatay, 5);
var yatay2 = new BoxView { Color = System.Drawing.Color.Gray };
gr.Children.Add(yatay2, 0, 2);
Grid.SetColumnSpan(yatay2, 5);
var yatay3 = new BoxView { Color = Xamarin.Forms.Color.Gray };
gr.Children.Add(yatay3, 0, 4);
Grid.SetColumnSpan(yatay3, 5);
var yatay4 = new BoxView { Color = Xamarin.Forms.Color.Gray };
gr.Children.Add(yatay4, 0, 6);
Grid.SetColumnSpan(yatay4, 5);
var soldik = new BoxView { Color = System.Drawing.Color.Gray };
gr.Children.Add(soldik, 0, 0);
Grid.SetRowSpan(soldik, 7);
var ortadik = new BoxView { Color = Xamarin.Forms.Color.Gray };
gr.Children.Add(ortadik, 2, 0);
Grid.SetRowSpan(ortadik, 7);
var sagdik = new BoxView { Color = System.Drawing.Color.Gray };
gr.Children.Add(sagdik, 4, 0);
Grid.SetRowSpan(sagdik, 7);
gr.Children.Add(new Label
{
Text = "Customer Name",
FontAttributes = FontAttributes.Bold,
TextColor = System.Drawing.Color.Yellow,
FontSize = 16,
Padding=new Thickness(10,10)
}, 1, 1); ;
gr.Children.Add(new Label
{
Text = "T.Type Name",
FontAttributes = FontAttributes.Bold,
TextColor= Xamarin.Forms.Color.Yellow,
FontSize=16,
Padding = new Thickness(10, 10)
}, 3, 1);
I made lines as grid column,row too. I think i made it wrong. When i add n row i need change rowspan too. Idk how can i make that project. Can you guys help me please ? I need learn : How can i add rows with entry , how can i add boxview and rowspan for new row (For make line) ? Thanks for help guys!
That photo for what should i do with my hand drawing : https://prnt.sc/10jxdhn
I can slove the problem by using Data binding.
First, edit your .xaml file like this:
<Entry Text="{Binding N}"></Entry>
<Button Text="Create" Command ="{Binding CreateCommand}"></Button>
<ListView ItemsSource="{Binding Rows}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding}"></Label>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Next create a ViewModel, I call it Page1ViewModel.cs.
In .xaml.cs file, add the binding context to Page1ViewModel in the constructor
BindingContext = new Page1ViewModel();
In Page1ViewModel.cs:
class Page1ViewModel : INotifyPropertyChanged
{
private int n;
private List<string> rows;
public List<string> Rows
{
get => rows;
set
{
rows = value;
OnPropertyChanged();
}
}
public int N
{
get => n;
set
{
n = value;
OnPropertyChanged();
}
}
public Command CreateCommand { get; }
public Page1ViewModel()
{
Rows = new List<string>();
CreateCommand = new Command(Create);
}
private void Create()
{
List <string> tmp = new List<string>();
for (int i = 0; i < n; i++)
{
tmp.Add("Row" + i);
}
Rows = tmp;
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Good luck!
I am working on a simple app that keeps track of life for a card game. I am very new to xamarin so I am starting small and just slowly adding more functionality. Currently, I have two pages; One page (the page it starts on (root page?) that has only one lifetotal number, two buttons for incrementing and decrementing, and one button to switch to a two player layout, and then a second page with two lifetotals and 4 buttons (an increment and decrement for each lifetotal). I am writing all of this in C# and I would like to keep it that way, however, I am having trouble finding a way to make it so that button that switches to the two player layout will present the second page. Everything ive googled seems to point back to xml which I want to avoid. Can anyone help me understand how to do this?
I am building off an app my buddy made for to understand how xamarin works so thats what all the weird comments are
code: (the delegate i need to fill in is at the bottom, called moreplayers)
namespace SampleApp
{
//contentpage is the base class for all pages.
//You should make a base class for this page that isn't contentpage, but inherits from content page, then you can add custom methods that extend across all pages.
//Like adding a progress spinner, or disabling all UI elements.
public class MainPage : ContentPage
{
public MainPage()
{
CreateUI();
}
private void CreateUI()
{
Stats Player1 = new Stats();
Player1.LifeTotal = 20;
//abstracting out a function to build UI is good, but breaking this down further is better.
var MainGrid = new Grid()//grids are the bread and butter of xamarin forms, the documentation has lots of good examples I won't try to replicate here.
{
HorizontalOptions = LayoutOptions.FillAndExpand,//these are on all UI elements, gotta specify them or the default values will probably screw up.
VerticalOptions = LayoutOptions.FillAndExpand
};
//I usually make a bunch of nice extensions on the Grid to add rows and columns easily
MainGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
MainGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
MainGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
//grid where life total label will live
var GridForLifeTotal = new Grid()
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
GridForLifeTotal.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
GridForLifeTotal.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
GridForLifeTotal.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
//grid where buttons will live
var GridForButtons = new Grid()
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
GridForButtons.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
GridForButtons.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
GridForButtons.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
MainGrid.Children.Add(GridForLifeTotal, 0, 0); //add items to the grid based on position
MainGrid.Children.Add(GridForButtons, 0, 1);
//Add labels
var lifeLabel = new Label()
{
Text = Player1.LifeTotal.ToString(),
FontAttributes = FontAttributes.Bold,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
FontSize = 60
};
GridForLifeTotal.Children.Add(lifeLabel, 0, 0);
//Add buttons
var UpButton = new Button()
{
Text = "+",
FontAttributes = FontAttributes.Bold,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
FontSize = 30
};
UpButton.Clicked += delegate {
//delegates are bad form but it's late and I'm tired you should put this login in a view model class and have that view model be a private property on this view.
//View (this), View Model (the logic layer) then a Model to hold the life total and any other user data?
Player1.LifeTotal += 1;
lifeLabel.Text = Player1.LifeTotal.ToString();
};
var DownButton = new Button()
{
Text = "-",
FontAttributes = FontAttributes.Bold,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
FontSize = 30
};
DownButton.Clicked += delegate {
//delegates are bad form but it's late and I'm tired
Player1.LifeTotal -= 1;
lifeLabel.Text = Player1.LifeTotal.ToString();
};
var MorePlayers = new Button()
{
Text = "2 Player Game",
FontAttributes = FontAttributes.Bold,
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.End,
FontSize = 30
};
MorePlayers.Clicked += delegate
{
//need to figure out what goes here
};
GridForButtons.Children.Add(UpButton, 0, 0);
GridForButtons.Children.Add(DownButton, 1, 0);
GridForButtons.Children.Add(MorePlayers, 0, 1);
Content = MainGrid;//very important, otherwise you don't actually see anything you've built
}
}
}
first, you need to wrap MainPage in a NavigationPage when you first assign it in your App.xaml.cs
MainPage = new NavigationPage(new MainPage());
then, to navigate to the next page in your delegate
this.Navigation.PushAsync(new Page2());
I am currently using the package ZXing.Net.Mobile for Xamarin Forms.
I want content on the top of the screen and at the bottom of the screen and I want the scanner to be somewhere in the middle.
If I specify the height of the scanner, it stretches it making it ugly and not nice to have (because the scanner is meant to be used for full screen?).
I want to have some content on the top of the screen with a dynamic height, then I want the scanner with height 150-200, then I want some content to be shown on the rest of the screen.
I was looking into ZXingDefaultOverlay but I could not get it to work as I wanted.
Anyone has an idea, example or an answer that can help me?
Following is the sample code where I have used Grid
for showing content on top and bottom of the screen and middle screen contains scanner.
public ZXingDefaultOverlay()
{
BindingContext = this;
RowSpacing = 0;
VerticalOptions = LayoutOptions.FillAndExpand;
HorizontalOptions = LayoutOptions.FillAndExpand;
RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
RowDefinitions.Add(new RowDefinition { Height = new GridLength(2, GridUnitType.Star) });
RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
Children.Add(new BoxView
{
VerticalOptions = LayoutOptions.Fill,
HorizontalOptions = LayoutOptions.FillAndExpand,
BackgroundColor = Color.Transparent,
Opacity = 0.7,
}, 0, 0);
Children.Add(new BoxView
{
VerticalOptions = LayoutOptions.Fill,
HorizontalOptions = LayoutOptions.FillAndExpand,
BackgroundColor = Color.Transparent,
Opacity = 0.7,
}, 0, 2);
StackLayout ImageLabelContainer = new StackLayout();
Image imgBox = new Image();
imgBox.Source = "scan_qr.png";
imgBox.VerticalOptions = LayoutOptions.Fill;
imgBox.HorizontalOptions = LayoutOptions.FillAndExpand;
ImageLabelContainer.Children.Add(imgBox);
Label lblSuccess = new Label();
lblSuccess.Margin = new Thickness(0, 7, 0, 0);
lblSuccess.HorizontalTextAlignment = TextAlignment.Center;
lblSuccess.TextColor = Color.Green;
lblSuccess.AutomationId = "zxingDefaultOverlay_BottomTextLabel";
lblSuccess.SetBinding(Label.TextProperty, new Binding(nameof(BottomText)));
ImageLabelContainer.Children.Add(lblSuccess);
Children.Add(ImageLabelContainer, 0, 1);
}
Here you can set height of the rows as per your requirement.
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;
}
I know that you can set the row height with a "*" in XAML this way:
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
but the same expression in C# returns an error:
new RowDefinition { Height = new GridLength("*", GridUnitType.Auto) },
So my question is how to set the row height of a grid to a "*" in C#?
var grid = new Grid ();
grid.RowDefinitions.Add (new RowDefinition { Height = GridLength.Auto });
grid.RowDefinitions.Add (new RowDefinition { Height = new GridLength (1, GridUnitType.Star) });
var stacklayout1 = new StackLayout { HeightRequest = 100, BackgroundColor = Color.Red };
var stacklayout2 = new StackLayout { BackgroundColor = Color.Blue };
Grid.SetRow (stacklayout2, 1);
grid.Children.Add (stacklayout1);
grid.Children.Add (stacklayout2);
MainPage = new ContentPage { Content = grid };