I am new on Xamarin.Forms and I am trying to use EntryCell
AccountId = new EntryCell {Label="Account Id", Text = CustomersPage.staticCustomer.AccountId};
When I am trying to add EntryCell to content page:
Content = new StackLayout {
Children = {
AccountId
}
};
I get the following error:
The best overloaded Add method
'System.Collections.Generic.ICollection.Add(Xamarin.Forms.View)'
for the collection initializer has some invalid arguments
Why can't I add EntryCell directly just like Entry?
EntryCell doesn't derive from View, therefore you cannot add it as a child to StackLayout children collection.
EntryCell is intented to use with ListView (also with TableView) control, generally due to performance reasons. EntryCell derives from Cell which provides description of a visual element rather than is a visual element.
On the other side Entry derives from View, thus you can add it to StackLayout.
Actullay I was searching away to use Label And Text on the same time So
As #Arkadiusz said
I used TableView like that :
TableView tb = new TableView();
tb.Root = new TableRoot() { new TableSection("Info") { AccountId }};
Content = new StackLayout { Children={ tb, ProcessToCheckOut } }
or
I need to user Entry && Label instead of EntryCell And Change stackLayout orientation To Horizontal
Related
I've been advised that Xamarin doesn't support nested ListViews.. I trying to build social app, in which the post might have several images and comments.
The feed page will be basically a ListView of the posts. While I cannot use a listView within the post (which is a viewCell), I tried to use Grid for the images instead, and another Grid for Comments. Both Images and Comments can be Lists, Arrays or ObservableCollections in the "post" Class.
Now I need to make foreach loop of this array/list, adding images with source bound to array item. But it seems to me, I couldn't use the data passed to the viewCell in C# (can only be used in Xaml layout).
Anybody has any ideas how to solve this.
[DataContract]
Public class post {
[DataMember]
List<comment> commentContainer {get; set;}
[DataMember]
List<String> imageContainer {get; set;}
}
in Xaml of cellView
<Grid x:Name="imagesGrid" IsVisible="{Binding isImage}" BindingContext="{Binding imageContainer}">
here I need to iterate the list of image in c# if possible - runtime- !
</Grid>
You are right to say that you shouldn't use nested ListViews in Xamarin.Forms, virtualization goes out the window and scrolling/gestures will be hard to handle.
However, i think this design in Xamarin.Forms will be fraught with problems. Xamarin.Forms ListView is a very specific beast and wont play well with very complicated layouts. My gut feeling is you want to do this in Native Views maybe or at the very least design this entirely in code. Anyway that is just my gut feel.
Have it be noted, i would shy away from this design and make it simple for your self by doing like WhatsApp does, and use a Template Selector and break apart multiple images and posts with a DataTemplateSelecto. Then you Don't have to worry about complicated layouts.
However, if you have your heart set on more complicated layouts inside ListView (be warned there be dragons) though you can take a look at this, Cell Appearance As noted i would be more inclined to this entirely in Code apposed to an ad-hock Xaml solution
public class CustomCell : ViewCell
{
public CustomCell()
{
//instantiate each of our views
var image = new Image ();
StackLayout cellWrapper = new StackLayout ();
StackLayout horizontalLayout = new StackLayout ();
Label left = new Label ();
Label right = new Label ();
...
//add views to the view hierarchy
horizontalLayout.Children.Add (image);
horizontalLayout.Children.Add (left);
horizontalLayout.Children.Add (right);
cellWrapper.Children.Add (horizontalLayout);
View = cellWrapper;
}
}
And set it like this
public partial class ImageCellPage : ContentPage
{
public ImageCellPage ()
{
InitializeComponent ();
listView.ItemTemplate = new DataTemplate (typeof(CustomCell));
}
}
Also checkout Grid
You can build one in code like this
var grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star)});
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star)});
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star)});
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star)});
var topLeft = new Label { Text = "Top Left" };
var topRight = new Label { Text = "Top Right" };
var bottomLeft = new Label { Text = "Bottom Left" };
var bottomRight = new Label { Text = "Bottom Right" };
grid.Children.Add(topLeft, 0, 0);
grid.Children.Add(topRight, 0, 1);
grid.Children.Add(bottomLeft, 1, 0);
grid.Children.Add(bottomRight, 1, 1);
I have a ListView and its ItemsSource.
ListView IList = new ListView();
IList.ItemsSource = _routine_names;
In order to customize the Data Template for each item I'm doing:
IList.ItemTemplate = new DataTemplate(()=>
{
Label Routine_Name = new Label(); // should be_routine_names
return new ViewCell
{
View = new StackLayout{
Children = {Routine_Name}
}
};
});
When I run this my ListView is displayed and the list items are indeed there (they have onclick handlers that work) but there is no text, which should be whatever is in _routine_names.
My question how do I get the Label in the DataTemplate to be items in _routine_names?
The reason I'm adding a DataTemplate is so I can add swipe to delete.
You can just use the built in TextCell for what you're trying to do. It has a bindable TextProperty and an optional DetailProperty if you want a smaller text line below the main one.
IList.ItempTemplate = new DataTemplate(()=>
{
var textCell = new TextCell();
textCell.ContextActions.Add(yourAction);
textCell.SetBinding(TextCell.TextProperty, ".");
return textCell;
}
IList.ItemsSource = _routine_names;
yourAction is of type MenuItem as seen here
Also, please notice that IList is a name of a class in System.Collection namespace so I'd use something else there.
I can create a new element of type Page in code behind, but I want to add children elements of type UIElement as I would to a Grid like: myGrid.Children.Add(myUIElement);
I don't have the Children property and setting the Content property does not work.How can I achieve this?
UPDATE:
This is what I have so far, but does not work:
Page myNewPage = new Page();
Grid myGrid = new Grid();
TextBlock myText = new TextBlock();
myText.Text = "I am a TextBlock!";
myGrid.Children.Add(myText);
myNewPage.Content = myGrid;
Frame.Navigate(myNewPage.GetType());
A Page can host a single UIElement in its Content property. To add several children, you have to do it like you would do it in XAML: add a panel that can contain and layout several children and add your elements to that panel.
In your question you talk about a grid called myGrid. You could add and layout your items in myGrid and then set myGrid as yourPage.Content.
Your code correctly builds the page. The problem with your code is that your Frame is navigating to a new instance of Page that is not the one that you created. Frame creates a new instance of the type that you pass as a parameter.
If you want to create a page fully in code, you can simply create class that extends Page and build the page in its constructor:
public class MyPage : Page
{
public MyPage()
{
this.BuildPage();
}
private void BuildPage()
{
var panel = new StackPanel();
panel.Children.Add(new TextBlock { Text = "Hello" });
panel.Children.Add(new TextBlock { Text = "World" });
this.Content = panel;
}
}
That's, after all, what the InitializeComponent method does in pages created in XAML.
I am adding tabs to my tab control through code:
TabItem tab = new TabItem();
var stack = new StackPanel() { Orientation = Orientation.Horizontal };
stack.Children.Add(new TextBlock() { Text = header });
stack.Children.Add(new TextBlock() { Name = "extra" });
tab.Header = stack;
tabControl.Items.Add(tab);
As you can see, it creates the header of the tabItem with a stack panel. It adds two text blocks; one of which is empty, but I've assigned the name "extra". What I would like to do is, later in the code, edit the textBlock named "extra" and add some new text to it.
How would I find and edit this element? I have tried the following code, but its producing an error saying the element can not be found:
object test = Application.Current.FindResource("extra");
FindName is what you are looking for but your TextBlock is not in the correct WPF Namescope.
MSDN states:
If you add an object to an object tree at a point in time after the XAML that produced that tree was parsed, a Name or x:Name value on the new object does not automatically update the information in a XAML namescope. To add a name for an object into a WPF XAML namescope after XAML is loaded, must call the appropriate implementation of RegisterName on the object that defines the XAML namescope.
For example:
var textBlock = new TextBlock() { Name = "extra" };
stack.Children.Add(textBlock );
RegisterName(textBlock);
...
TextBlock textBlock = FindName("extra") as TextBlock;
Finally, Application.Current.FindResource("extra") is returning null because the element does not exist when project resources are created. More on FindResource.
Just use FrameworkElement.FindName method:
var control = tab.FindName("extra");
if(control is TextBlock){
// your logic here
}
You don't need Application.Current.Resource dictionary here because it's different collection. If you want to use it then you should put user controls within Resource dictionary beforehand.
Because you are trying to find resource with the key "extra". It's wrong.
Try this:
TabItem tab = new TabItem();
var stack = new StackPanel() { Orientation = Orientation.Horizontal };
var textBlock = new TextBlock() { Name = "extra" }
stack.Children.Add(new TextBlock() { Text = header });
stack.Children.Add(textBlock);
tab.Header = stack;
tabControl.Items.Add(tab);
Now you can reach it with textBlock instance.
Here's some VB WPF code for what you need
Dim test As TextBlock
test = DirectCast(FindName("extra"), TextBlock)
I have no idea if it will work like that in C# WPF although if that doesn't work try looking up CType
I've created a view that will need to be added to several different screens. I'm struggling to figure out how to align the elements correctly in the view.
The output needs to look like the following:
I've tried the following with no success:
var uiiv = new UIImageView(image);
var firstLine = new UITextField { Text = description};
var secondLine = new UITextField { Text = summary};
this.Add(uiiv);
this.Add(firstLine );
this.Add(secondLine );
Every UI element should have a Frame property that allows you to specify the position of the element relative to it's parent view. Using this property will allow you to position the element.