I developing application for windows-phone,
I want to create table with 2 rows an 2 columns
I create xaml code for this table
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions/>
</Grid>
I want to create this Grid in code
Grid chat_userpicgrid = new Grid();
newgrid.Children.Add(chat_userpicgrid);
But I don't know how to create RowDefinitions and ColumnDefinitions.
Grid newGrid = new Grid();
newGrid.Background = new SolidColorBrush(Colors.White);
newGrid.ColumnDefinitions.Add(new ColumnDefinition());
newGrid.ColumnDefinitions.Add(new ColumnDefinition());
newGrid.RowDefinitions.Add(new RowDefinition());
newGrid.RowDefinitions.Add(new RowDefinition());
To position elements in specific cells:
Grid chat_userpicgrid = new Grid();
Grid.SetColumn(chat_userpicgrid, 1);
Grid.SetRow(chat_userpicgrid, 1);
newGrid.Children.Add(chat_userpicgrid);
Have a look at the code at the bottom of this MSDN page
Related
I have a Listview which has toggle switches. I want to select only one item in Listview with toggle switch. When I select second toggle then first toggle must be de-active again. For example in the picture; When I select Rekorida and then I select Merchandizing , Rekorida must turn back disable. Every time only one option can be active. Is it possible to do it in Xamarin?
My listView Code :
<ScrollView>
<ListView x:Name="ShipListView" HasUnevenRows="True" SeparatorVisibility="Default" SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Margin="4, 3, 4, 3" Padding="2" BackgroundColor="White">
<Grid.RowDefinitions HeightRequest="40">
<RowDefinition></RowDefinition>
<!--<RowDefinition Height="20"></RowDefinition>-->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="40*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Text="{Binding ShipName}" TextColor="DeepPink" Grid.Column="0" FontAttributes="Bold"/>
<Switch IsToggled="{Binding Selected}" Grid.Column="2" Toggled="OnShipToggled" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
And My function
async void OnShipToggled(object sender, ToggledEventArgs e)
{
checkShipSelected = !checkShipSelected;
if(checkShipSelected)
{
ViewCell cell = (sender as Switch).Parent.Parent as ViewCell;
ParametersMemberShipInformation model = cell.BindingContext as ParametersMemberShipInformation;
if (model != null)
{
selectedMemberShipOid = model.Oid;
}
}
else
{
return;
}
}
I'm trying get id of selected item in listview and I do this successfully. Bu I want users can only select one item at the same time because of nice visuality and not be confused.
Fetch your view model in your code behind file and then filter out the selected toggle and marked rest of them as false
private YourViewModel MyViewModel { get => BindingContext as YourViewModel; }
if (model != null)
{
selectedMemberShipOid = model.Oid;
MyViewModel.ShipListView.Where(x=> x.Oid !=
selectedMemberShipOid).Foreach(x=> x.Selected = false)
}
I have made a very similar post about this earlier where I asked how to reuse a part of some Xaml code. Although that worked for the small element I had, it does not quite work on the current scale.
Using Xamarin, I have a tabbed layout with two pages. A page consists of a grid with three layers, two of which are the same on both pages. The third layer needs to be different on both pages. Both pages are currently in the same file. This means that a large portion of the code is simply a copy-paste, and it makes it more difficult to edit values of certain labels in those first two rows since they can't have similar IDs / Names.
I currently set a string variable in the codebehind with a setter.
string _vesselCode;
public string VesselCode
{
get
{
return _vesselCode;
}
set
{
_vesselCode = value;
currentVessel.Text = _vesselCode;
currentVesselClone.Text = currentVessel.Text;
}
}
Although this works, I still have a lot of duped code (as shown below).
This is the content of each page. The only page-specific content is at the bottom. The rest is literately copy-pasted to the second page. Code below is without any IDs.
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<!-- first row from top {0} - app name, vessel. -->
<RowDefinition Height="Auto"/>
<!-- second row {1} - originele freq // nieuwe frequentie. -->
<RowDefinition Height="Auto"/>
<!-- third row {2} - tablayout. -->
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- header contents -->
<Grid Grid.Row="0" StyleClass="headerBar">
<StackLayout Grid.Column="0" HorizontalOptions="Start" StyleClass="inGrid">
<Label StyleClass="header"
Text="OV Frequentie"/>
<Label StyleClass="headerSub"
Text="huidig voertuig:"/>
</StackLayout>
</Grid>
<!-- freq bar contents -->
<Grid Grid.Row="1" StyleClass="subHeaderBar">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<BoxView Grid.ColumnSpan="2"
BackgroundColor="#2d313a"
WidthRequest="2"
HeightRequest="2"
Margin="5,0,5,-3"/>
<StackLayout Grid.Column="0" HorizontalOptions="Start" StyleClass="inGrid">
<Label StyleClass="generalSmallText"
Text="originele freq: 10"/>
</StackLayout>
<StackLayout Grid.Column="1" HorizontalOptions="End" StyleClass="inGrid">
<Label StyleClass="generalSmallText"
Text="nieuwe freq: 10"/>
</StackLayout>
</Grid>
<!-- info page content -->
<Grid Grid.Row="2">
<StackLayout StyleClass="infoDisplayPage">
<!-- page unique stuff -->
</StackLayout>
</Grid>
</Grid>
Like I said, this sort of works, but is incredibly bad code. There are multiple Labels I want to be able to change the value of, but I can't give them the same ID. This means I have to either always set those values twice, or get some set attribute on one of the Labels, automatically setting the other one / have attributes in the code behind with such setter.
I got told that for using bigger area's of code, I could use a ContentView. However, I can't seem to reuse them across two ContentPages.
How do I make it so I can reuse the code of the first two grid rows on both pages, and be able to have different contents of the third grid layout? I'm OK with having to possibly set both Labels using the codebehind as above if that is needed.
I'm quite new to app development, so any extra source of explenation of the code below is appriciated.
I need to use OnIdiom for grid column definition, but it isn't working. See my code below. Can anyone tell me what I am doing wrong and suggest a solution?
<Grid.ColumnDefinitions>
<ColumnDefinition>
<ColumnDefinition.Width>
<OnIdiom x:TypeArguments="GridLength" Tablet="64.9*" Phone="99.8*"/>
</ColumnDefinition.Width>
</ColumnDefinition>
<ColumnDefinition>
<ColumnDefinition.Width>
<OnIdiom x:TypeArguments="GridLength" Tablet="0.1*" Phone="0.1*"/>
</ColumnDefinition.Width>
</ColumnDefinition>
<ColumnDefinition>
<ColumnDefinition.Width>
<OnIdiom x:TypeArguments="GridLength" Tablet="35*" Phone="0.1*"/>
</ColumnDefinition.Width>
</ColumnDefinition>
This does not help, so I did:
<Grid.ColumnSpan>
<OnIdiom x:TypeArguments="x:Int32" Phone="3" Tablet="1"/>
</Grid.ColumnSpan>
This also not helps.
x:DataType instead of x:TypeArguments works for me..
<Grid.RowDefinitions>
<RowDefinition >
<RowDefinition.Height>
<OnIdiom x:DataType="GridLength" Tablet=".25*" Phone="0.075*" />
</RowDefinition.Height>
</RowDefinition>
<RowDefinition >
<RowDefinition.Height>
<OnIdiom x:DataType="GridLength" Tablet="*" Phone="0.85*" />
</RowDefinition.Height>
</RowDefinition>
<RowDefinition >
<RowDefinition.Height>
<OnIdiom x:DataType="GridLength" Tablet=".25*" Phone="0.075*" />
</RowDefinition.Height>
</RowDefinition>
</Grid.RowDefinitions>
override void OnSizeAllocated(double width, double height)
{
//according with height and width you can design your layouts
if (Device.Idiom == TargetIdiom.Phone)
{
// layout views vertically
}
else
{
// layout views horizontally or use different Page
}
}
I'm working on a Windows 10 app. and i created map in my second page.. but it is too slow.. Is it possible to preload the contents of a page before displaying it to the user so that the transition from page x to page y is smooth?
Is not possible, all pages in uwp apps will be rendered when you navigated to some page.
But you can prepare the data before to navigate to your second page maybe you can save this data in the local storage and load the data in the method OnNavigatedTo in your second page it would be better.
The easiest option is probably to not make it a page at all; instead, have the map on the page you are starting from, but have its Opacity be zero. Then when you want to show it, set the Opacity to one. This if course means you pay the cost of loading the map even if the user never wants to view it, but it makes viewing instant.
Sample XAML:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button Content="go to map" Click="GoToMap" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Grid x:Name="mapLayer" xmlns:maps="using:Windows.UI.Xaml.Controls.Maps" Opacity="0" IsHitTestVisible="False">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<maps:MapControl />
<Button Content="back" Click="HideMap" HorizontalAlignment="Center" Grid.Row="1"/>
</Grid>
</Grid>
And matching code:
private void GoToMap(object sender, RoutedEventArgs e)
{
mapLayer.Opacity = 1;
mapLayer.IsHitTestVisible = true;
}
private void HideMap(object sender, RoutedEventArgs e)
{
mapLayer.Opacity = 0;
mapLayer.IsHitTestVisible = false;
}
See the following XAML:
<UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400" MinHeight="150">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<sdk:DataGrid x:Name="grid" VerticalScrollBarVisibility="Visible" />
<Button x:Name="button" Grid.Row="1" Content="hello" VerticalAlignment="Top" HorizontalAlignment="Center" Click="button_Click" />
</Grid>
</UserControl>
Corresponding code:
public partial class MainPage : UserControl
{
public class dataclass
{
public string data { get; set; }
}
ObservableCollection<dataclass> list;
public MainPage()
{
InitializeComponent();
grid.ItemsSource = list = new ObservableCollection<dataclass>();
}
private void button_Click(object sender, RoutedEventArgs e)
{
for (var i = 0; i < 5; i++)
list.Add(new dataclass
{
data = "hello" + i
});
}
}
How it works now: The grid takes up the entire screen height minus the height of the button. When too many new items are added, you scan start scrolling. The position of the button never changes, it's always at the bottom of the screen.
What I would like: The grid should take up as little space as possible, so when it's empty, only the header should be visible, and the button immediately below it. When too many items are added, and the button is already at the bottom of the screen, it shouldn't grow any more, but start scrolling instead.
If I swap the two RowDefinition's, then the grid is small at first, but grows indefinitely, pushes the button off the screen and never starts scrolling. How can I do this nicely?
In order to achieve this, nest another Grid in LayoutRoot and then use that nested grid as your main one. Then set both rows to Auto.
<Grid x:Name="LayoutRoot" Background="White">
<Grid x:Name="innerGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid x:Name="itemInTheFirstRow" Grid.Row="0" />
<Button x:Name="itemInTheSecondRow" Grid.Row="1" />
</Grid>
</Grid>
Finally, you need to track the size of the grid and change the sizing rules accordingly. This "pinning" code looks something like.
RowDefinition row = this.innerGrid.RowDefinitions[0];
if (row.Height.GridUnitType == GridUnitType.Auto)
{
if (this.innerGrid.ActualHeight > this.ActualHeight)
{
row.Height = new GridLength(1, GridUnitType.Star);
}
}
else
{
if (this.itemInTheFirstRow.DesiredSize.Height < row.ActualHeight)
{
row.Height = GridLength.Auto;
}
}
In my implementation, I wrap this code in an UpdateRowPinning method that actually uses the dispatcher to call this code. I then call UpdateRowPinning on resize events for the main grid and the inner grid as well as on adding and removing items from the grid and expand/collapse operations of grid groups. This ensures that the second row behaves properly by sitting at the base of the first row until the screen is full and then floating over it after that.
My answer here also covers this issue. I searched for a XAML only solution but it just doesn't seem possible (unless you write some XAML extensions, then you might be able to pull it off with XAML but that's kind of cheating).