ItemTemplate DesignTime hints for custom control - c#

I would like to create custom control with ItemsSource, which ItemTemplate for these items.
I have made it working, but one thing is left:
I would like to have DesignTime helper for binding within DataTemplate. Right now I can bind properties from Collection object, but there's no hints in XAML like with other bindings.
Of course I can do something like this:
<DataTemplate>
<StackPanel d:DataContext="{d:DesignInstance models:User}">
<Label Content="{Binding FirstName}" />
<Label Content="{Binding LastName}" />
</StackPanel>
</DataTemplate>
But I would like to avoid DesignTime instances entered manually.
Is there a way to do this?

<DataTemplate DataType={x:Type User}>
By telling the DataTemplate the type that it represents; intellisense will give you DesignTime hints as to the properties available for Binding expressions

Related

Assigning multiple views to one viewmodel WPF C#

I have an application where I assign each of the views datacontext through the datatemplate in xaml.
The problem is I now have a viewmodel implemented as a singleton and need to have two views using it.
Is there some way to set multiple views in the one datatemplate?
Something like below which I know does not work, I am just using this as an example of what I mean:
<DataTemplate DataType="{x:Type viewModel:ThisViewModel}">
<view:ViewOne />
<view:ViewTwo />
</DataTemplate>
Thanks
I'm not sure if I understand you entirely, but it sounds like you need to assign a Key to your DataTemplates
<DataTemplate x:Key="DataTemplate1" DataType="{x:Type viewModel:ThisViewModel}">
<view:ViewOne />
</DataTemplate>
<DataTemplate x:Key="DataTemplate2" DataType="{x:Type viewModel:ThisViewModel}">
<view:ViewTwo />
</DataTemplate>
Then from your regular XAML, you would specify what template you want to use for each area via it's key, like this:
<ContentControl Content="{Binding MyViewModel}"
ContentTemplate="{DynamicResource DataTemplate1}" />
<ItemsControl ItemsSource="{Binding MyViewModels}"
ItemTemplate="{DynamicResource DataTemplate2}" />
If I misunderstood and you actually want one data template containing two Views, there's no problem with that. DataTemplates can have as many elements as you want, however they can only have one main child element, so make that element a panel that is used to tell WPF how to arrange the two views.
<DataTemplate x:Key="DataTemplate1" DataType="{x:Type viewModel:ThisViewModel}">
<StackPanel>
<view:ViewOne />
<view:ViewTwo />
</StackPanel>
</DataTemplate>
Yes its possible to add two Views to a DataTemplate like below,
<DataTemplate x:Key="KeyName" DataType="{x:Type viewModel:ThisViewModel}">
<Grid>
<view:ViewOne />
<view:ViewTwo />
</Grid>
</DataTemplate>
DataTemplate can have more than one view by adding any kind of Panel as a parent Control, like Grid, StackPanel, WrapPanel etc all based on how you want to display it on the View.

Hide last item in a ItemsControl

I've a ItemsControl that I bind to my viewmodel, but inside the datatemplate I also have an image. I want that image to be visible as long as it's not the last item in the list, then it should be hidden (it's an arrow that point down to the next control).
The xaml look like this:
<ItemsControl ItemsSource="{Binding PageContainers}" x:Name="Items">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<controls:DesignControl DataContext="{Binding}" MouseDown="UIElement_OnMouseDown" MouseUp="UIElement_OnMouseUp" MouseMove="UIElement_OnMouseMove"/>
<Image Source="/Resources/Images/arrow.png" Height="16" Width="16" Margin="0,10,0,0"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
So is there any easy to check if the Image/Stackpanel is last in the list? I guess I could subscribe to some event and do it in the code behind, but I guess it's cleaner if I could do it inside the xaml.
You're binding to PageContainers which I assume to be a collection. Can the type of that collection be extended to include an IsLast property?
If it can, you can bind the visibility to that.

How can I reuse XAML tags in WPF?

I was wondering whether it was possible to instead of me copying pieces of code in XAML, to define something that I could link to. In more concrete terms, what I have is:
<Grid>
// Definitions
<Label Content="Name:" />
<Label Content="Age:" Grid.Column="1"/>
...
<Grid>
and now I would like to have something like <Content_in_grid=nice_labels> and it should simply copy these labels.
Notice: I do not want the grid, because these are some labels that I would like to bind with different properties.
PS: maybe a different perspective, imagine I would like to create a file properties comparison program with WPF. So you can imagine that I have to copy all those labels such as Filename, Date etc. static labels again, but for maintainability, if I would like to change Filename to File then I would have to search and replace instead of editing it in one place.
Thanks in advance.
Add it in the resources:
<Window.Resources>
<DataTemplate x:Key="MyGrid">
<Grid>
<Label Content="Name:" />
<Label Content="Age:" Grid.Column="1" />
</Grid>
</DataTemplate>
</Window.Resources>
And then use it where you want:
<StackPanel>
<ContentPresenter ContentTemplate="{StaticResource MyGrid}" />
<ContentPresenter ContentTemplate="{StaticResource MyGrid}" />
<ContentPresenter ContentTemplate="{StaticResource MyGrid}" />
</StackPanel>
What you are describing is templating the content based on a collection of items (you mentioned a file properties comparison tool, so I am guessing it could be a list of file properties).
You would in reality not add the Labels over and over again to a Grid, but would let the Binding system do it for you using (in your case) a HeaderedItemsControl such as a DataGrid.
<DataGrid ItemsSource="{Binding FileProperties}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding PropertyName}" Header="Name:"/>
<DataGridTextColumn Binding="{Binding PropertyValue}" Header="Age:"/>
</DataGrid.Columns>
</DataGrid>
NB: FileProperties used in the ItemsSource would normally be an ObservableCollection<T> of a type that has PropertyName and PropertyValue properties.
You could achieve a similar effect using an ItemsControl and some static XAML for the header, but this is much neater overall.
The answer from Flat Eric is almost correct.
I added x:Shared="False" though, because otherwise the Resource could only be used once and would only be visible in the last ContentPresenter. (It is visible in all ContentPresenters in the VisualStudio, but not in the final application).
PS: I saw that Flat Eric edited his answer, so that x:Shared is not necessary anymore. Anyway, the original answer, should be like this:
<Grid x:Key="MyGrid" x:Shared="False" >
<Label Content="Name:"/>
<Label Content="Age:" Grid.Column="1"/>
</Grid>

C# WPF Binding to DataBase

Hei all. If something would be not clear then please tell
I have dataGrid and TreeView.
I have loaded data base as Entity Data Model and some tables.
One of these tables "relation" should show to the datagrid. But its (relation table) column depend of the other tables as system,model,function and device. In the Data grid should be 4 columns which contain names of these system,model,function and device. (the picture 1 as should be)
Problem in the how it all show. DataSource don't work well... see picture 2.
<Grid DataContext="{StaticResource relationsViewSource}">
<DataGrid AutoGenerateColumns="True" Name="gridInventory" HorizontalContentAlignment="Right" Margin="255,12,12,128" ItemsSource="{Binding}" />
<StackPanel Height="391" HorizontalAlignment="Left" Margin="10,10,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="239" DataContext="{StaticResource systemsViewSource}" >
<TreeView Height="391" Name="treeView1" Width="239" VerticalContentAlignment="Top" HorizontalAlignment="Left" VerticalAlignment="Top" ItemsSource="{Binding}" />
</StackPanel>
</Grid>
Picture 1:
Picture2:
You are binding both the TreeView and some of your DataGrid columns to an object, but not telling WPF how to draw the object. When WPF doesn't know how to draw an object, it by default draws it using a TextBlock with the Text bound to the object's .ToString()
You need to set the ItemTemplate to tell WPF how to draw your individual objects, such as this:
<TreeView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</TreeView.ItemTemplate>
You could also use an implicit DataTemplate to tell WPF how to draw specific objects. This is just a DataTemplate that specifies a DataType without a Key, and WPF will use it anytime it tries to render an object of the specified type.
If you want to avoid removing AutoGenerateColumns="True" and manually specifying your DataGrid's columns, this is probably the method to use.
<DataGrid.Resources>
<DataTemplate DataType="{x:Type local:Device}">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</DataGrid.Resources>
The TreeView you would need to set the Path on the Binding to the property you want to display,
The Devices is a collection and you need to put a Listview in there or something that will display a collection and then put a DataTemplate on it to display what you need, either that or bind to a converter to return a static string representation of the Device list
Or just get someone to do it all for you as seems the case on here lol

Optimal way to populate a large number of textboxes in MVVM

I'm currently creating a WPF application using MVVM. I have a large number of textboxes in a window (about 20) that need to be bound to specific elements in a list and need to be populated all at once. Normally I'd push them into an array and populate them that way but I can't do so without breaking the MVVM model. Is there a quick and efficient way I can do this while still adhering to MVVM?
You could bind your list to an ItemsControl and change it's item template to be a TextBox.
<ItemsControl ItemSource={Binding aList}>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Text}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I don't see why strictly this would break MVVM, if instead of using an Array you used a List, put it in your ViewModel and then use indexed binding to bind to specific elements.
Something like:
<StackPanel>
<TextBox Text="{Binding MyViewModelList[0]}">
<TextBox Text="{Binding MyViewModelList[1]}">
<TextBox Text="{Binding MyViewModelList[2]}">
</StackPanel>
or if you want something more dynamic, instead of List, put an ObservableCollection in your VM, and bind to it in an ItemsControl with a DataTemplate.
<ItemsControl ItemsSource="{Binding Path=MyViewModelObsCol}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Syntax might not be 100% as I don't have an IDE to test, but something along these lines might be what you're after.
If you are trying to populate textbox on the bases of selection in list box try this
Another option is creating a COllection view source which i don't think you will require here

Categories