UWP GridView in C# with DataTemplate - c#

I have a Grid where I want to put a GridView in every cell of it from the code-behind in the .xaml.cs. The problem is that I do not know how to create a GridView with a DataTemplate to bind stuff in it in C#
DataTemplate Template= new DataTemplate();
GridView gridView = new GridView();
gridView.ItemsSource = book;
Thats all I have. Help is appreciated
J.

I want to put a GridView in every cell of it from the code-behind in the .xaml.cs.
You could make a DataTemplate in App.xaml file like follow.
<Application.Resources>
<ResourceDictionary>
<DataTemplate x:Key="template">
<StackPanel>
<TextBlock Text="{Binding }"/>
</StackPanel>
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
And use it in the code behind.
private void SetUpUI()
{
var gridView = new GridView();
//DataTemplate usage.
gridView.ItemTemplate = (DataTemplate)App.Current.Resources["template"];
gridView.ItemsSource = new List<string> { "fas", "fasd", "fasf" };
RootLayout.Children.Add(gridView);
}

Related

UWP Grid inside Datatemplate

I have a Pivot where I set the header in my Pivot.HeaderTemplate it is basically just showing Names of Books. In my Pivot.ItemTemplate I want to show a Grid which is build in my .xaml.cs but since the Grid is in my DataTemplate I can not access the Grid x:Name anymore in the code behind in .xaml.cs. books is a Collection of Books which contains a Name and a Title
MainPage.xaml
<Pivot ItemsSource="{x:Bind books}">
<Pivot.HeaderTemplate>
<DataTemplate x:DataType="local:Book">
<TextBlock Text="{x:Bind Name}"/>
</DataTemplate>
</Pivot.HeaderTemplate>
<Pivot.ItemTemplate>
<DataTemplate>
<Grid
x:Name="BooksGrid"
BorderBrush="Black" BorderThickness="1 1 0 0"
Margin="0 10 0 0>
</Grid>
</DataTemplate>
</Pivot.ItemTemplate>
Now I want to acces BooksGrid iny the code behind and actually create the Grid
MainPage.xaml.cs
public MainPage()
{
this.InitializeComponent();
}
private void DrawGrid()
{
//create columns of Grid
for (int i = 0; i < booksize.XProperties.Count + 1; i++)
{
BooksGrid.ColumnDefinitions.Add(new ColumnDefinition
{
});
}
BooksGrid.ColumnDefinitions[0].Width = GridLength.Auto;
}
....
Already here at BooksGrid.ColumnDefinitions.Add(...) I get the error that BooksGrid can not be found.
My DrawGrid works if I do not place the Grid definition in my DataTemplate and also outside myPivot. So the MainPage.xaml.csdoes not find it when the Grid is inside my DataTemplate
I've read that the solution might be that I have to acces the Grid instance that I want to work with, as soon as the DataTemplate gets loaded. But I do not know how to do that either.
EDIT PART to first solution:
I'm also using BooksGrid in another method
MainPage.xaml.cs
private void DrawBooksFront(Front front)
{
int row;
int column;
column = booksize.XProperties.IndexOf(front.CustomProps[booksize.XLabel])+1;
row = booksize.YProperties.IndexOf(front.CustomProps[booksize.YLabel])+1;
Frame newFrame = new Frame();
TaskBoardGrid.Children.Add(newFrame);
Grid.SetColumn(newFrame, column);
Grid.SetRow(newFrame, row);
}
The reason you cannot access your BooksGrid is because it will be dynamically generated for each book in the books collection. So for every book a Grid will be generated.
OPTION 1:
You can add a Loaded event to your grid:
<Pivot x:Name="Pivot" ItemsSource="{x:Bind books}">
<Pivot.HeaderTemplate>
<DataTemplate x:DataType="local:Book">
<TextBlock Text="{x:Bind Name}"/>
</DataTemplate>
</Pivot.HeaderTemplate>
<Pivot.ItemTemplate>
<DataTemplate>
<Grid
BorderBrush="Black" BorderThickness="1,1,0,0"
Margin="0,10,0,0" Loaded="DrawGrid">
</Grid>
</DataTemplate>
</Pivot.ItemTemplate>
and in your code behind:
private void DrawGrid(object sender, RoutedEventArgs e)
{
Grid grid = sender as Grid;
// Load your grid..
}
EDIT - OPTION 2:
If you'd like to access your grids from code behind in a different way (like suggested in your edit) you can always do the following:
private void DrawBooksFront(Front front)
{
// Loop through the pivot's items and get the content from each item's ContentTemplate.
foreach (var item in Pivot.Items)
{
PivotItem pivotItem = Pivot.ContainerFromItem(item) as PivotItem;
Grid grid = pivotItem.ContentTemplate.LoadContent() as Grid;
// Do something with the grid.
}
}
If your goal is to display previews of the pages of the book inside a PivotItem in a grid-like manner [picture below], then you're better off placing GridView in a DataTemplate of Pivot.ItemTemplate and using data binding to display those pages automatically, this would eliminate the need to write the code in xaml.cs that you showed.
Please, share more details about your app (what you're given and what the end result should look like) so we could help you better.

Textboxes binded to SelectedItem of a code-behind created DataGrid don't actualize

I'm experimenting with code-behind created WPF masks as prototype for a WPF mask designer.
In my ViewModel i have a DataTable and a DataView (which is simply the DefaultView of the DataTable).
In my DataTable i got two columns ("vorname" and "nachname") and four rows.
In my WPF mask i want to have a DataGrid and two TextBoxes, which are binded to the SelectedItem of the DataGrid and the columns (either "vorname" or "nachname").
When i select an item in the DatGrid at runtime, the data from that item shall be showed in the TextBoxes.
First i tried to define the DataGrid in the XAML file and generate the TextBoxes an their bindings in code.
Here it works fine.
I select an item in the DataGrid and the data of the item is showed in the TextBoxes.
But when i generate the grid in code, it doesn't work anymore.
Is there some sort of NotifyOnSelectedIndexChanged, that i'm missing?
Any help will be appreciated.
This is the XAML:
<Window x:Class="DesignerTest.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow"
Height="400"
Width="600">
<DockPanel x:Name="mainpanel">
<!--<DataGrid x:Name="datagrid"
DockPanel.Dock="Top"
Height="120" />-->
<WrapPanel x:Name="wrappanel">
<!--<TextBox x:Name="vornameSelected" Width="150" Margin="5" Text="{Binding SelectedItem.vorname, ElementName=datagrid}" IsEnabled="False" />
<TextBox x:Name="nachnameSelected" Width="150" Margin="5" Text="{Binding SelectedItem.nachname, ElementName=datagrid}" IsEnabled="False" />-->
<!--<TextBox x:Name="vornameSelected" Width="150" Margin="5" IsEnabled="False" />
<TextBox x:Name="nachnameSelected" Width="150" Margin="5" IsEnabled="False" />-->
</WrapPanel>
</DockPanel>
</Window>
And this is the code for creating and binding:
// The ViewModel und the DataTable are created.
_vm = new SerializingTestViewModel();
_vm.CreateDataTable();
this.DataContext = _vm.DataTable;
// The DataGrid and it's Binding are created.
DataGrid datagrid = new DataGrid();
datagrid.Name = "datagrid";
DockPanel.SetDock(datagrid, Dock.Top);
datagrid.Height = 120;
datagrid.ItemsSource = _vm.DataSource;
mainpanel.Children.Add(datagrid);
// The Textboxes and the Bindings are created.
TextBox vornameSelected = new TextBox();
vornameSelected.Name = "vornameSelected";
vornameSelected.Width = 150;
Thickness margin = new Thickness(5);
vornameSelected.SetValue(TextBox.MarginProperty, margin);
vornameSelected.IsEnabled = false;
Binding selectedItemBinding = new Binding();
selectedItemBinding.ElementName = "datagrid";
selectedItemBinding.Path = new PropertyPath("SelectedItem.vorname");
vornameSelected.SetBinding(TextBox.TextProperty, selectedItemBinding);
wrappanel.Children.Add(vornameSelected);
TextBox nachnameSelected = new TextBox();
nachnameSelected.Name = "nachnameSelected";
nachnameSelected.Width = 150;
margin = new Thickness(5);
nachnameSelected.SetValue(TextBox.MarginProperty, margin);
nachnameSelected.IsEnabled = false;
selectedItemBinding = new Binding();
selectedItemBinding.ElementName = "datagrid";
selectedItemBinding.Path = new PropertyPath("SelectedItem.nachname");
nachnameSelected.SetBinding(TextBox.TextProperty, selectedItemBinding);
wrappanel.Children.Add(nachnameSelected);
Try setting your binding source using the Source property instead of ElementName
//selectedItemBinding.ElementName = "datagrid"
selectedItemBinding.Source = datagrid;
The problem might be that the ElementName lookup for items is not working as expected because items are added dynamically at runtime via code behind.

convert xaml template binding to code behind

I have a gridcontrol which is populated from database. Also, in code, I added to datatable a checkeditsettings column. I created a template in xaml , but I can't manage to convert it in C#. In my code below,
XAML code:
<dxg:GridColumn FieldName="Select" Fixed="Right" UnboundType="Boolean">
<dxg:GridColumn.EditSettings>
<dxe:CheckEditSettings />
</dxg:GridColumn.EditSettings>
<dxg:GridColumn.CellTemplate>
<DataTemplate>
<local:MyCheckEdit
IsChecked="False"
IsEnabled='True'
Checked="MyCheckEdit_Checked"
EnabledChecked="/Images/mark.png"
EnabledUnchecked="/Images/markk.png"
DisabledUnchecked="/Images/marken.png" >
</local:MyCheckEdit>
</DataTemplate>
</dxg:GridColumn.CellTemplate>
</dxg:GridColumn>
What I have tried so far:
GridColumn colselect = new GridColumn();
ComboBoxEditSettings c = new ComboBoxEditSettings();
colselect.EditSettings = c;
DataTemplate template = new DataTemplate();
template.VisualTree = new FrameworkElementFactory(typeof(MyCheckEdit));
template.VisualTree.SetBinding(MyCheckEdit.ContentProperty, new Binding("...?"));
colselect.CellTemplate = template;
I am really stack here.
Keep the DataTemplate in a Resources section in xaml, give it a name (x:Key) and just reference it from code-behind when you need it:
<dxg:DataGrid x:name="myGrid" >
<dxg:DataGrid.Resources>
<DataTemplate x:Key="MyCellTemplate" >
<local:MyCheckEdit IsChecked="False"
IsEnabled='True'
Checked="MyCheckEdit_Checked"
EnabledChecked="/Images/mark.png"
EnabledUnchecked="/Images/markk.png"
DisabledUnchecked="/Images/marken.png" />
</DataTemplate>
</dxg:DataGrid.Resources>
...
</dxg:DataGrid>
Then, in your code-behind:
GridColumn colselect = new GridColumn();
colselect.EditSettings = new ComboBoxEditSettings();
colselect.CellTemplate = myGrid.Resources["MyCellTemplate"] as DataTemplate;

WPF Edit Templated Column by Code

I'm trying to edit the contents of an StackPanel inside a templated DataGrid Column by Code. Unfortunately i cannot find the StackPanel from Code. Can anybody help me, please?
This is my DataTemplate:
<UserControl.Resources>
<DataTemplate x:Key="ReservationContainerTemplate">
<StackPanel Orientation="Horizontal" Background="Black" />
</DataTemplate>
</UserControl.Resources>
This is how I create this Column:
var colReservations = new DataGridTemplateColumn();
colReservations.Header = "Nordplatz";
DataTemplate dt = null;
dt = dataGrid1.FindResource("ReservationContainerTemplate") as DataTemplate;
colReservations.CellTemplate = dt;
dataGrid1.Columns.Add(colReservations);
What I need to do is, writing to this StackPanel inside DataTemplate.
I was able to get the Object by following Code:
DataRowView n = (DataRowView)dataGrid1.Items[i];
//var m = dataGrid1.SelectedItem.Cells[0].Text;
DataTemplate Template = dataGrid1.FindResource("ReservationContainerTemplate") as DataTemplate;
StackPanel stp = Template.LoadContent() as StackPanel;
Great, I've got my Object, but how can I modify it? Under this conditions i've only got a copy of the Object, changes are not reflected to the original one.
Does anybody have got an idea?

nested xaml elements - rewrite it in code

I need to create a DataGridColumn from code.
The XAML equivalent would be:
<data:DataGridTemplateColumn Header="Name" Width="100">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" TextTrimming="WordEllipsis"></TextBlock>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
I've started like that:
DataGridTemplateColumn column = new DataGridTemplateColumn
{
Header = "Name",
Width = 100,
};
TextBlock inside = new TextBlock {TextTrimming = TextTrimming.CharacterEllipsis};
But I don't know how to 'merge' such puzzles. There are nested elements in XAML, how to achieve this from code?
A good way to do this is to pack the entire XAML snippet into a string and call XamlReader.Load() or XamlReader.Parse() on it. The bonus feature of this approach is that it'll work in Silverlight as well (with some fiddling), where you can't build DataTemplates in code.
Almost there, change your code to this and it should work:
DataGridTemplateColumn column = new DataGridTemplateColumn
{
Header = "Name",
Width = 100,
};
FrameworkElementFactory ftb = new FrameworkElementFactory(typeof(TextBlock));
Binding b = new Binding("Name");
ftb.SetValue(TextBlock.Text, b);
ftb.SetValue(TextBlock.TextTrimming, TextTrimming.CharacterEllipsis);
DataTemplate ct = new DataTemplate();
ct.VisualTree = ftb;
column.CellTemplate = ct;
Another method besides the above is to define your datatemplate in XAML within your resources then dynamically load it in the code:
XAML:
<Window.Resources>
<DataTemplate x:Key="myCellTemplate">
<TextBlock Text="{Binding Name}" TextTrimming="WordEllipsis" />
</DataTemplate>
</Window.Resources>
Code:
DataGridTemplateColumn column = new DataGridTemplateColumn
{
Header = "Name",
Width = 100,
};
column.CellTemplate = this.FindResource("myCellTemplate") as DataTemplate;

Categories

Resources