In a datatemplate that I am binding to a viewmodel I have a grid like so:
<Grid>
.
. <!--Row & Col Definitions...-->
.
<TextBlock Text="Some Label" Style="{DynamicResource TextBlockLabelStyle}" />
<TextBlock Grid.Column="1" Text="{Binding SomeValue, Mode=OneWay}"/>
<Border Style="{DynamicResource SeparatorStyle}" />
<TextBlock Grid.Row="1" Text="Some Label" Style="{DynamicResource TextBlockLabelStyle}" />
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding SomeValue, Mode=OneWay}"/>
<Border Grid.Row="1" Style="{DynamicResource SeparatorStyle}" />
<TextBlock Grid.Row="2" Text="Some Label" Style="{DynamicResource TextBlockLabelStyle}" />
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding SomeValue, Mode=OneWay}"/>
<Border Grid.Row="2" Style="{DynamicResource SeparatorStyle}" />
</Grid>
I thought that adding this repeated pattern (TextBlock for label, TextBlock for value, horizontal rule) was getting tedious and thought it would be best to encapsulate it into a UserControl something like 'GridRow' e.g.:
<UserControl x:Class="GridRow">
<TextBlock Text="{Binding LabelText}" Style="{DynamicResource TextBlockLabelStyle}" />
<TextBlock Grid.Column="1" Text="{Binding ValueText, Mode=OneWay}"/>
<Border Style="{DynamicResource SeparatorStyle}" />
</UserControl>
Then I could just go something like:
<Grid>
<GridRow LabelText="Some Label" ValueText="{Binding SomeValue}"/>
<GridRow Grid.Row="1" LabelText="Some Label2" ValueText="{Binding SomeValue2}"/>
<GridRow Grid.Row="2" LabelText="Some Label3" ValueText="{Binding SomeValue3}"/>
</Grid>
and have the user control bind to LabelText and ValueText properties, perhaps through template binding?
My question is how to do this, and if this is the right way of doing it, or if it is possible to use Styles or datatemplates to do this?
Unfortunately this is something that is not easy to achieve. A Grid layout looks at the Grid.Row and Grid.Column properties of its immediate children in order to create the required layout. Therefore, nesting your UI controls in another Grid will break the layout.
A few options, this blog post fixes the problem, but is complex:
http://www.scottlogic.co.uk/blog/colin/2010/11/using-a-grid-as-the-panel-for-an-itemscontrol/
There is a nice Auto-grid here, I have not used it, but it looks pretty good:
http://whydoidoit.com/2010/10/06/automatic-grid-layout-for-silverlight/
Regards,
Colin E.
Related
I want to move focus from Title Textbox to Textbox in ContentControl in WPF.
But any command doesn't work.
How can I move focus?
<TextBox
Grid.Row="0"
MinWidth="200"
Name="Title"
VerticalContentAlignment="Center"
mahApps:TextBoxHelper.ClearTextButton="True"
mahApps:TextBoxHelper.Watermark="Task Title"
Text="{Binding Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<StackPanel
Grid.Row="1"
Margin="0,5,0,5"
Background="White">
<ContentControl
MinHeight="55"
Margin="5"
Content="{Binding CreateTaskControl}" />
</StackPanel>
you can use Focusable="True" and KeyboardNavigation.TabIndex="1"
And of course if TabIndex you did not use it.
this code Focusable="True" and KeyboardNavigation.TabIndex="1" Useful for places that do not accept the TabIndex element, such as TextBlock
I am trying to design a layout for a custom control for a project I am working on and got it looking the way I would like it to look, the problem is that from functional point of view I don't believe it is going to work for what I really need it to do. The following can be dropped into a Window to get the look I am going for.
<Window x:Class="TestProject.MainWindow"
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"
xmlns:local="clr-namespace:TestProject"
mc:Ignorable="d"
Title="MainWindow" Height="1080" Width="1920">
<StackPanel Margin="15,80,1535.333,85.667">
<Border BorderBrush="#FFD9D9D9" BorderThickness="0,1.5,0,0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="35" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.ColumnSpan="3" Background="#FFF1F1F1">
</StackPanel>
<StackPanel Grid.Column="1" Margin="0,1,20,3" VerticalAlignment="Center">
<TextBlock FontSize="18" FontWeight="SemiBold">Header</TextBlock>
</StackPanel>
<StackPanel Grid.Column="2" Margin="0,1,10,3" VerticalAlignment="Center">
<TextBlock HorizontalAlignment="Right" FontWeight="SemiBold" FontSize="18">$125,400.00</TextBlock>
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="1" Margin="0,2,20,2">
<TextBlock Foreground="#FF383838" FontSize="18" Margin="0,2">Test 1</TextBlock>
<TextBlock Foreground="#FF383838" FontSize="18" Margin="0,2">Test 2</TextBlock>
<TextBlock Foreground="#FF383838" FontSize="18" Margin="0,2">Test 3</TextBlock>
<TextBlock Foreground="#FF383838" FontSize="18" Margin="0,2">Test 4</TextBlock>
<TextBlock Foreground="#FF383838" FontSize="18" Margin="0,2">Test 5</TextBlock>
</StackPanel>
<StackPanel Grid.Column="2" Grid.Row="1" Margin="0,2,10,2">
<TextBlock HorizontalAlignment="Right" Foreground="#FF383838" FontSize="18" Margin="0,2">$0.00</TextBlock>
<TextBlock HorizontalAlignment="Right" Foreground="#FFBB0808" FontSize="18" Margin="0,2">$-100.00</TextBlock>
<TextBlock HorizontalAlignment="Right" Foreground="#FF383838" FontSize="18" Margin="0,2">$125,000.00</TextBlock>
<TextBlock HorizontalAlignment="Right" Foreground="#FF383838" FontSize="18" Margin="0,2">$1,000.00</TextBlock>
<TextBlock HorizontalAlignment="Right" Foreground="#FFBB0808" FontSize="18" Margin="0,2">$-500.00</TextBlock>
</StackPanel>
</Grid>
</Border>
</StackPanel>
</Window>
Now the issue I am struggling with is turning this is a template, that can be used with a binding, and I was thinking that I should maybe have gone with a listview and Grid View for the column headers. So any advice would be appreciated here as well.
The above has a few things I can see as an issue, mainly that I would need to click on each item row that will then run some code, and that is why I feel that I should have gone with a Grid View option instead. But the one reason I didn't go with the Grid View, was mainly because I could see no way to do the same layout here, with the columns.
So to recap
Should I have gone with a Grid View, if so how can I get the same results with the scaling of the middle column?
Best way to go about learning to turn this into a custom control, that I can style. Mainly looking for an explanation, resources to learn from.
Edit:
For those following or interested, the part I am struggling with is the following section. How would I do this from data binding, and get the template to be controlled to look this way? I understand the binding part, it's the actual template to control the data in the same way as the following code demonstrates.
<StackPanel Grid.Column="1" Grid.Row="1" Margin="0,2,20,2">
<TextBlock Foreground="#FF383838" FontSize="18" Margin="0,2">Test 1</TextBlock>
<TextBlock Foreground="#FF383838" FontSize="18" Margin="0,2">Test 2</TextBlock>
<TextBlock Foreground="#FF383838" FontSize="18" Margin="0,2">Test 3</TextBlock>
<TextBlock Foreground="#FF383838" FontSize="18" Margin="0,2">Test 4</TextBlock>
<TextBlock Foreground="#FF383838" FontSize="18" Margin="0,2">Test 5</TextBlock>
</StackPanel>
<StackPanel Grid.Column="2" Grid.Row="1" Margin="0,2,10,2">
<TextBlock HorizontalAlignment="Right" Foreground="#FF383838" FontSize="18" Margin="0,2">$0.00</TextBlock>
<TextBlock HorizontalAlignment="Right" Foreground="#FFBB0808" FontSize="18" Margin="0,2">$-100.00</TextBlock>
<TextBlock HorizontalAlignment="Right" Foreground="#FF383838" FontSize="18" Margin="0,2">$125,000.00</TextBlock>
<TextBlock HorizontalAlignment="Right" Foreground="#FF383838" FontSize="18" Margin="0,2">$1,000.00</TextBlock>
<TextBlock HorizontalAlignment="Right" Foreground="#FFBB0808" FontSize="18" Margin="0,2">$-500.00</TextBlock>
</StackPanel>
The reason to use a custom control is because you want to re-template it entirely for theming. They are more complicated than usercontrols or templating and if you don't need theming functionality then a usercontrol or template would be the way to go.
It does look like a listview would do what you're looking for.
You would want a row viewmodel which exposed a brush to bind foreground of the second column to.
And that column would look something like:
ForeBrush being a public solidcolorbrush.
Brushes are arguably a view responsibility so you could use an enum or some such instead. And a converter to translate that into a brush.
The whole of that markup could then be turned into a datatemplate and your data into a viewmodel. Use type of that viewmodel to template it into the ui via the datatype matching your viewmodel.
<DataTemplate DataType="{x:Type local:CostingsListViewModel}"
<ListView>
.....
Or you could put it in a UserControl
<DataTemplate DataType="{x:Type local:CostingsListViewModel}"
<local:CostingsListView/>
I have a Grid in which I have a RichTextBox control for the description text and there is a ToolTip attached with that RichTextBox. Please check the below code-
<Grid Grid.Row="1" >
<controls:RichTextBox Text="{Binding Description, Mode=TwoWay}"
VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" IsEnabled="False" />
<Grid.ToolTip>
<ToolTip>
<TextBlock Text="{Binding Path=Descriptiontext}"
TextTrimming="CharacterEllipsis" TextWrapping="Wrap" />
</ToolTip>
</Grid.ToolTip>
</Grid>
And I wanted to set "ToolTipService.ShowDuration" property for ToolTip. But I am not getting a way, where to attach it.
Can anyone suggest how we can do that.
The ShowDuration property is actually an attached property from the contained TooltipService. You can put it either on the ToolTip itself or the parent Grid. i.e.
<Grid Grid.Row="1" ToolTipService.ShowDuration="5000">
<controls:RichTextBox Text="{Binding Description, Mode=TwoWay}"
VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" IsEnabled="False" />
<Grid.ToolTip>
<ToolTip>
<TextBlock Text="{Binding Path=Descriptiontext}"
TextTrimming="CharacterEllipsis" TextWrapping="Wrap" />
</ToolTip>
</Grid.ToolTip>
</Grid>
I want to display the following using a wpf TreeView:
My objects are different, there is no Base class or Interface, I must define a HierarchicalDataTemplate for each item, STOP for example I can add just one ItemSource "Deliveries" but I want to add the pickups also for this stop.
<!-- DELIVERY-->
<DataTemplate x:Key="DeliveryDataTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="DeliveryId" Margin="3,3" />
<TextBlock Text="{Binding DeliveryStatus}" VerticalAlignment="Center" Margin="5" />
<TextBlock Background="{Binding StopStatus, Converter={StaticResource StatusConverter}}" Width="16" Height="16" />
</StackPanel>
</DataTemplate>
<!-- STOP -->
<HierarchicalDataTemplate x:Key="StopTemplate"
ItemsSource="{Binding Deliveries}"
ItemTemplate="{StaticResource DeliveryTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Stop" Margin="3,3" />
<TextBlock Text="{Binding StopId}" Margin="3,3" />
<TextBlock Background="{Binding StopStatus, Converter={StaticResource StatusConverter}}" Width="16" Height="16" Margin="3,3" />
</StackPanel>
</HierarchicalDataTemplate>
<!-- ROUTE -->
<HierarchicalDataTemplate x:Key="RouteTemplate"
ItemsSource="{Binding Stops}"
ItemTemplate="{StaticResource StopTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Route" Margin="5,5" />
<TextBlock Text="{Binding RouteId}" Margin="5,5" />
<TextBlock Background="{Binding RouteStatus, Converter={StaticResource StatusConverter}}" Width="16" Height="16" Margin="5,5" />
</StackPanel>
</HierarchicalDataTemplate>
I have a collection of Routes, each Route has Stops, each Stop has Deliveries and Pickups, each Delivery has its items each item has its own items and so on... How to solve this?
This sounds like a heterogenous datasource problem. I think this solution might be what you are looking for.
I like this answer because it need some very short codes.
WPF Treeview Databinding Hierarchal Data with mixed types
And you might need reading this question to import the System.Windows.Data.ObservableCollection Class. To be short, it can only be imported in a Wpf Library or so, not in a normal .net Class Library.
Cannot Import System.Windows.Data
I'm having an issue with tabbing through the controls on a WPF application using the MVVM pattern. I have the following XAML which defines a tree structure
<Grid Background="Transparent" Margin="10">
<TreeView ItemsSource="{Binding FirstLevelNavigableViewModels}" Background="Transparent"
HorizontalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
BorderThickness="0"
ItemContainerStyle="{StaticResource TreeViewItemStyle1}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type ViewModel:VendorViewModel}" ItemsSource="{Binding Children}">
<View:VendorView HorizontalContentAlignment="Stretch" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type ViewModel:ProductViewModel}">
<View:ProductView HorizontalContentAlignment="Stretch" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
When the treeview is loaded, the XAML for the "ProductView" is as follows
<Border Margin="0,2,2,2" CornerRadius="3" Background="#3FC7B299" DockPanel.Dock="Right" HorizontalAlignment="Right" Width="109">
<StackPanel Orientation="Vertical" Margin="6,4">
<DockPanel>
<TextBlock DockPanel.Dock="Left" FontFamily="Segoe" FontSize="10" FontWeight="Medium"
Foreground="Black" Opacity="0.75"
Text="CALC. REG. PRICE"></TextBlock>
<Button Width="10" Height="10" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Padding="-4" Margin="0" Command="{Binding UserDefinedRetailPriceCommand}" Visibility="{Binding UserDefinedRetailPriceButtonView}">
<Image Width="10" Height="10" Source="/Arhaus.Pricing.Client;component/Styles/Images/error.png"></Image>
</Button>
</DockPanel>
<TextBox FontFamily="Segoe" FontSize="16" FontWeight="Medium" KeyboardNavigation.IsTabStop="True" KeyboardNavigation.TabIndex="{Binding RegularPriceTabIndex}"
Foreground="Black" Opacity="0.9" KeyboardNavigation.TabNavigation="Continue"
ebf:LostFocusBehaviour.LostFocusCommand = "{Binding LostFocusSugg}"
Text="{Binding NewSuggestedRetailPrice,Converter={StaticResource FormattingConverter}, ConverterParameter=' \{0:C\}', Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Background="#FFE6DED3" BorderBrush="#FFE6DED3" DataContext="{Binding StringFormat=\{0:c\}, NotifyOnValidationError=True}" Padding="0" TabIndex="1"></TextBox>
</StackPanel>
</Border>
I have the Tab Index bound to an integer that is ever increasing and bound as the treeview is loaded (I.E. I have it setup as tab index 1, 2, 3 etc. as each successive model is loaded).
I would like to be able to hit tab and jump to the next textbox in the treeview but when I click the TAB key, nothing happens. I'm not sure if I have the tabbing setup correctly but I'm very new to WPF and at a loss as to where and how to set the tabbing to make it work. I'm used to WinForms where you just set the tab index and go from there.
Thank you for your assistance, I apologize for the large code block.
I don't have a solution ready but some thoughts that maybe may help:
I don't know what RegularPriceTabIndex returns but probably it begins for each new TreeViewItem at the same index?
The same tab-index is given then multiple times because of repeating use of ProductView. Perhaps this leads to a problem. You can try setting FocusManager.IsFocusScope="true" for the ProductView. Maybe this helps.
Try also to set Control.IsTabStop="true" on the TextBox.