Optimal way to populate a large number of textboxes in MVVM - c#

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

Related

Auto-scroll Listbox based on TextBox text

In WPF and MVVM pattern, I have a TextBox and a ListBox. The ListBox is bound to a collection of items using a DataTemplate. The default count for this collection is about 50 or so.
What I wanted to achieve is a filter-like action. If it's possible, I wouldn't like to change the list view or anything like that, but simply to scroll to the item corresponding to the TextBox match, preferably without selecting it.
I've seen some examples and solutions using CollectionView and Filter (couldn't get it to work btw), and some using auto-scroll to the end of the list or to a new added item, but none specific to my case.
My Listbox is structured as follows:
<ListBox IsTextSearchEnabled="True" HorizontalAlignment="Stretch" Margin="6,49,0,0" Name="lbObjectA" VerticalAlignment="Stretch" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type src:Dto}">
<StackPanel Height="20" Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}" Margin="0,3,0,0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

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.

Display data from two levels down

I have the following classes, which contain ObservableCollections of the next level down:
Draw
ObservableCollection<Round>();
Round
ObservableCollection<Formation>();
Formation
So a Draw is made up of Rounds, Rounds are made up of Formations.
I have a page which has a button to create a random draw, I currently have it calling another class which returns a draw:
this.defaultViewModel[DrawName] = RandomDraw.generate();
I am having no problem binding a ListView to Rounds and displaying round information, but how do I display the individual formations? This is what I am currently doing, I was not expecting to be able to just display things by binding to Formations but how do I access it?
<ListView
ItemsSource="{Binding Rounds}"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,9.5">
<TextBlock
Text="{Binding RoundNumber}"
TextWrapping="Wrap"
Pivot.SlideInAnimationGroup="1"
CommonNavigationTransitionInfo.IsStaggerElement="True"
Style="{ThemeResource ListViewItemTextBlockStyle}"
Margin="0,0,19,0"/>
<TextBlock
Text="{Binding Formations}"
TextWrapping="WrapWholeWords"
Pivot.SlideInAnimationGroup="2"
CommonNavigationTransitionInfo.IsStaggerElement="True"
Style="{ThemeResource ListViewItemContentTextBlockStyle}"
Margin="0,0,19,0"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
You should take a look at Hierarchical Data Templates, which are used by the WPF TreeView control rather than ListViews. They are a natural fit to show hierarchical data. Of course, like any WPF control, you can completely customize their appearance using styling and templates. Here are some good references:
MSDN How to: Use a TreeView to Display Hierarchical Data
Hierarchical Databinding in WPF
However, if you would like to keep using ListViews, then one way to do this is to nest another container control inside the parent ListVIew. ObservableCollections are processed automatically by specific WPF elements, such as Panels. In your example, you can replace the second TextBlock with another ListView, with an ItemTemplate similar to the first. It can also be any Collection-like Panel element, such as StackPanel.
<ListView
ItemsSource="{Binding Rounds}"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,9.5">
<TextBlock
Text="{Binding RoundNumber}"
TextWrapping="Wrap"
Pivot.SlideInAnimationGroup="1"
CommonNavigationTransitionInfo.IsStaggerElement="True"
Style="{ThemeResource ListViewItemTextBlockStyle}"
Margin="0,0,19,0"/>
<!-- CHANGED CODE HERE -->
<ListView
ItemsSource="{Binding Formations}"
...>
<ListView.ItemTemplate>...</ListView.ItemTemplate>
</ListView>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Making clickable URLs in RichTextBox using bindings

My XAML has a DataTemplate defined which has ItemsSource set to some data class, which holds properties that will be presented in UI. One property is "Files", which has to display one or more files in the form of <Hyperlink NavigateUri="URLtoFILE">Filename</Hyperlink> (optional filesize).
The property is currently of type string where I'm concatenating different files' URLs and text together. But the stuff I put into that property display on screen verbatim.
I've seen this: WP8: RichTextBox has no Document property, but I have the problem of using data templates and bindings, which makes referencing the RichTextBox object in code impossible (is it?).
How can I mix text and clickable URLs within a WP8 control that is using data templates and bindings?
EDIT: If it helps, the ItemsSource always holds only one object.
EDIT: Part of XAML
<Grid>
<phone:LongListSelector x:Name="List">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel>
<RichTextBox IsReadOnly="True">
</RichTextBox>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</Grid>
You want to show a list of urls?
If you want this :
<lisbox itemSource={Binding YourItemSource} selectedItem="{Binding ItemProperty}">
<listbox.ItemTemplate>
<dataTemplate>
<textblock>
<Hyperlink Command="{Binding HyperLinkTapped}" NavigateUri="URLtoFILE"></Hyperlink>
</textblock><
</datatemplate>
</listbox.itemtemplate>
</listbox>

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

Categories