Trigger usercontrol storyboard from inner contentcontrol in wpf - wpf

I have two usercontrols:
Usercontrol 1:
- contains a storyboard animation in the usercontrol resources named "somestoryboard".
- contains a keyboard that has to be slide up when someone clicks on a textbox in usercontrol 2.
- contains a contentcontrol where any usercontrol dynamically resides.
Usercontrol 2:
- Contains a textbox with an eventtrigger. When touched the storyboard from usercontrol 1 has to be fired.
Unfortunately the whole binding goes wrong in the second user control. I constantly get the message "couldn't find object of storyboard".
How do I set this binding right in usercontrol 2, or is this even possible in purely xaml?
Here are the two usercontrols:
Usercontrol 1:
<UserControl (some namespaces)>
<UserControl.Resources>
<Storyboard x:Key="SomeControl">
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="aControl"
Storyboard.TargetProperty="Expanded" >
<DiscreteBooleanKeyFrame Value="True" KeyTime="0:0:0" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="500" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="800" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid Grid.Column="1" Grid.Row="1" Background="{StaticResource DefaultBackground}" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition />
<RowDefinition Height="70" />
</Grid.RowDefinitions>
<ContentControl Grid.Row="1" Grid.Column="2" Margin="10,0,20,0" VerticalContentAlignment="Top"/>
</Grid>
<Controls:Somecontrol x:Name="aControl" VerticalAlignment="Bottom" Height="0" HorizontalAlignment="Stretch"
Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="1" Grid.RowSpan="2" UseAnimation="True"
Style="{StaticResource AnimatedControl}" />
</Grid>
Usercontrol 2:
<UserControl (some namespaces)>
<Grid Margin="5" >
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Text="{Binding InputMessage}" VerticalAlignment="Center" FontSize="12" Margin="0,0,0,5" />
<TextBox Grid.Row="1" Text="{Binding InputResult}" InnerBorderBrush="Blue" CornerRadius="5" Background="White" >
<TextBox .Triggers>
<EventTrigger RoutedEvent="TextBox.TouchUp">
<BeginStoryboard Storyboard="{StaticResource SomeControl}" />
</EventTrigger>
</TextBox.Triggers>
</TextBlock >
</Grid>
</UserControl>

Related

Enable Button if One of Three Textboxes across 3 tabs has content

I have a Button that lives outside a tab control element. Each Tab on the TabControl has either a text box for manual text entry or a search tool to look up something from a database (the value of which will also be written to the label in tab 2 & 3).
I want to enable the Print button if the textbox has content or a variable that is populated from a database query on the selected tab has content.
What would be the best way to do this, given a button can only be bound to one source? I pondered having a staging variable, but then that would also be only bound to one element.
Any ideas? I'm really new to data-binding and I'm struggling to get my head around some of the concepts.
It doesn't help that the back-end is in VB because i'm porting a number of WinForms apps to WPF and I want to do them properly.
Quick XAML:
<Window x:Name="Main1" x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" SizeToContent="Height">
<Grid>
<StackPanel >
<Grid x:Name="Activity" Margin="5,5,5,0" >
<StackPanel>
<TabControl x:Name="Main_Tabs" Background="{x:Null}" BorderBrush="Gainsboro">
<TabItem x:Name="T1" Header="H1" >
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="80*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right">Address:</Label>
<TextBox x:Name="Single_Address"
Margin="5,3"
SpellCheck.IsEnabled="True"
IsManipulationEnabled="True"
TextWrapping="Wrap"
AcceptsReturn="True"
VerticalScrollBarVisibility="Auto"
Grid.Column="1" Grid.Row="2"
Language="en-GB" Height="80">
</TextBox>
</Grid>
</TabItem>
<TabItem x:Name="T2" Header="H2" >
<Grid Grid.ColumnSpan="2" Grid.Row="1" x:Name="Grid_Elucid_Label2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="80*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right">Address:</Label>
<Label x:Name="Elucid_Address"
Margin="5,3"
Grid.Column="1" Grid.Row="2" Height="80">
</Label>
</Grid>
</TabItem>
<TabItem x:Name="T3" Header="H3">
<Grid x:Name="Grid_Sage_Label" Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="80*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right">Address:</Label>
<Label x:Name="Sage_Address" Margin="5,3" Grid.Column="1" Grid.Row="2" Height="80">
</Label>
</Grid>
</TabItem>
</TabControl>
</StackPanel>
</Grid>
<Button x:Name="Print_Button" Content="Print" Padding="10" Background="{x:Null}" BorderBrush="Gainsboro" />
</StackPanel>
</Grid>
</Window>
#1 VM with few textproperties to evaluate
if you have just a few text properties and use a VM, you can go with some triggers.
I wrote this by hand so I'm sorry if the syntax isn't a 100% match.
<button content="print">
<button.style>
<style targettype={x:type button}>
<style.triggers>
<multidatatrigger>
<multidatatrigger.conditions>
<condition Binding="{Binding VMprop1}" Value="">
<condition Binding="{Binding VMprop2}" Value="">
<condition Binding="{Binding VMprop3}" Value="">
</multidatatrigger.conditions>
<multidatatrigger.setters>
<setter property="IsEnabled" value="false"/>
</multidatatrigger.setters>
</multidatatrigger>
</style.triggers>
</style>
</button.style>
<button>
2 no VM or a lot of properties to evaluate
bind to the TextChanged of all TextBoxes and evaluate their state, and set the IsEnabled from your button (if you want use a Dependency Property)
<button x:Name="btn1" content="print" IsEnabled="{Binding CanPrint}"/>
<textbox x:Name="tb1" TextChanged="EvaluateCanPrint"/>
<textbox x:Name="tb2" TextChanged="EvaluateCanPrint"/>
<textbox x:Name="tb3" TextChanged="EvaluateCanPrint"/>
<textbox x:Name="tb4" TextChanged="EvaluateCanPrint"/>
...
private void EvaluateCanPrint() {
// ViewModel.EvaluateCanPrint();
ViewModel.CanPrint =
!string.isNullOrEmpty(tb1.Text) &&
!string.isNullOrEmpty(tb2.Text) &&
...;
}
// Original answer
//private void EvaluateTextChanged() {
// if (string.isNullOrEmpty(tb1.Text) &&
// string.isNullOrEmpty(tb2.Text) &&
// ...)
// {
// btn1.IsEnabled = false;
// }
//}

Application memory rapidly increases when resizing with Grid controls

I have a couple Grid's in my application and the memory usage goes from 70MB up to 300MB when I continuously resize the window (as in making it smaller, bigger, repeat).
There are no bindings or events in my application and I have already removed any Auto layout option I had for rows/columns.
Is this just normal because I have so many Grid's or is there something wrong with my layout?
Video: https://i.gyazo.com/e6292fa9b4e065bf1842c69cbd43b853.mp4
<Window x:Class="CanvasDrawTest.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:CanvasDrawTest"
mc:Ignorable="d"
Title="MainWindow"
Height="863"
Width="1443"
WindowStyle="SingleBorderWindow"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20" />
<!-- TopGrid -->
<RowDefinition />
<!-- MainGrid -->
<RowDefinition Height="30" />
<!-- FooterGrid -->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid Name="TopGrid" Grid.Row="0" Grid.Column="0">
<Menu>
<MenuItem Header="File">
<MenuItem Name="NewDiagramMenuItem" Header="New Diagram" Click="NewDiagramMenuItem_Click" />
</MenuItem>
</Menu>
</Grid>
<DockPanel LastChildFill="True" Grid.Row="1" Grid.Column="0">
<Grid Name="MainGrid" DockPanel.Dock="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75*"/>
<ColumnDefinition Width="643*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,0,0.333">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Grid.Row="0" Grid.Column="0" BorderBrush="Gray" BorderThickness="0,0,0.4,0">
<Grid Name="LeftGrid" />
</Border>
<Grid Name="CenterGrid" Grid.Row="0" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="150" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid Name="ContentGrid" Grid.Row="0" Grid.Column="1">
<TabControl Name="DocumentTabs" BorderThickness="0" />
</Grid>
<Border Grid.Row="1" Grid.Column="1" BorderBrush="Gray" BorderThickness="0,0.4,0,0">
<Grid Name="BottomGrid" />
</Border>
</Grid>
</Grid>
</Grid>
</DockPanel>
<Grid Name="FooterGrid" Grid.Row="2" Grid.Column="0">
<StatusBar Name="StatusBar" Height="30" />
</Grid>
</Grid>
</Window>

Unable to bind to gridview in another usercontrol

I have 3 user controls
One is the parent that holds a GridViewUserControl and a ExportUserControl
The GridViewUserControl and ExportUserControl have their own viewmodels.
When I click the ExportButton in the ExportUserControl I need to pass the gridview to a command in the ExportUserControl. Everything I try is always passing null.
How would I do something like this? ( This is giving the error "binding.elementname cannot be set while using binding.relativesource"
<telerik:RadButton Content="Export"
Command="{Binding ExportCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=view:GridViewUserControl}, ElementName=GridViewData}"
Margin="0,10,0,0" />
EDIT: Parent Control looks like this
<UserControl x:Class="Sample.Sample1.View.ParentUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:view="clr-namespace:GroundStation.Configuration.Viewer.View"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
DataContext="{Binding Source={StaticResource Locator}, Path=Main}">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="150"/>
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<view:ExportUserControl Margin="5"
Grid.Column="0"
Grid.Row="2"
Grid.RowSpan="2"
MinWidth="150"
/>
<GridSplitter Grid.Column="1"
Width="5"
Grid.Row="1"
Grid.RowSpan="3"
HorizontalAlignment="Stretch" />
<view:GridViewUserControl
Margin="5"
Grid.Column="2"
Grid.Row="1"
Grid.RowSpan="3"/>
</Grid>
</UserControl>

Docking the buttons at the bottom

I am trying to dock the 2 buttons at the bottom of the window, so that they are always there when I resize the window. Obviously I am doing it wrong since it won't work. Here is my code. I have also seen from examples that some people uses the DockPanel.Dock on the controls and not the container itself. I can't do this for some reason. Using DockPanel.dock on the button gives an error.
My question is: How do I make the buttons (Or the stackPanel) dock at bottom?
<Window x:Class="MeditCal.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<DockPanel LastChildFill="True">
<StackPanel DockPanel.Dock="Top">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0">Date</Label>
<TextBox Grid.Row="1" Name="DateTxtBox" Background="WhiteSmoke"/>
<Label Grid.Row="2">Note</Label>
<TextBox Grid.Row="3" Name="noteTxtBox"
Background="WhiteSmoke"></TextBox>
</Grid>
<Popup Height="100" Width="100" Name="popUpWin" StaysOpen="false"
AllowsTransparency="True"
HorizontalAlignment="Center" PopupAnimation="Fade">
<Border BorderThickness="1" Background="AliceBlue">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Record added" />
</StackPanel>
</Border>
</Popup>
<ListView Name="msgArea" Background="WhiteSmoke" MinHeight="150"
Height="138" />
</StackPanel>
<DockPanel LastChildFill="True">
<StackPanel DockPanel.Dock="Bottom">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Name="addButton" Content="Add" Grid.Column="0"
Grid.Row="1" />
<Button Name="getRecordsButton" Content="Get records"
Grid.Column="1" />
</Grid>
</StackPanel>
</DockPanel>
</DockPanel>
It isn't very clear what kind of layout you're trying to achieve. I would suggest you to remove the inner DockPanel and it's StackPanel child, because each of them only contains single child which is an indication that you don't need a panel wrapper there.
Something like this will make the Grid containing buttons placed at bottom, and the StackPanel fill remaining space in the DockPanel :
<DockPanel LastChildFill="True">
<Grid DockPanel.Dock="Bottom">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Name="addButton" Content="Add" Grid.Column="0" Grid.Row="1" />
<Button Name="getRecordsButton" Content="Get records" Grid.Column="1" />
</Grid>
<StackPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0">Date</Label>
<TextBox Grid.Row="1" Name="DateTxtBox" Background="WhiteSmoke"/>
<Label Grid.Row="2">Note</Label>
<TextBox Grid.Row="3" Name="noteTxtBox" Background="WhiteSmoke"></TextBox>
</Grid>
<Popup Height="100" Width="100" Name="popUpWin" StaysOpen="false" AllowsTransparency="True"
HorizontalAlignment="Center" PopupAnimation="Fade">
<Border BorderThickness="1" Background="AliceBlue">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Record added" />
</StackPanel>
</Border>
</Popup>
<ListView Name="msgArea" Background="WhiteSmoke" MinHeight="150" Height="138" />
</StackPanel>
</DockPanel>

Scrollable Grid in WPF/Silverlight

I would like to build a WPF window which uses an outer Grid to split the screen into 4 parts. In the lower right quadrant, I would like to embed another Grid which is larger than the grid cell. I have been looking for ways to add a ScrollViewer (or use the Grid.ScrollViewer properties) but no matter what I try the inner grid does not resize or display the scrollbars appropriately.
I suspect it has something to do with not wrapping the inner grid with the correct panel with the appropriate sizing (and resizing) behavior which would force the inner grid to honor the scrollbars, instead of simply rendering too big (and being clipped by the other window).
The hosting window is defined like this:
<Window x:Class="GridScrollTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:GridScrollTest"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="OuterGrid">
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<local:SSControl x:Name="Sheet"
Grid.Row="1" Grid.Column="1"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Yellow" />
<Canvas Grid.Row="0" Grid.Column="0" Background="LightGreen" />
<Canvas Grid.Row="1" Grid.Column="0" Background="LightBlue" />
<Canvas Grid.Row="0" Grid.Column="1" Background="LightCoral" />
</Grid>
</Window>
And the referenced SSControl:
<UserControl x:Class="GridScrollTest.SSControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Height="270" Width="600">
<ScrollViewer
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
CanContentScroll="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid x:Name="CellGrid" ShowGridLines="False"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
</Grid>
</ScrollViewer>
</UserControl>
I do not know for sure, but after trying your code in Blend, I think your problem might be that you have set the ColumnDefinition.Width and RowDefinition.Height to Auto. Try setting them to * and remove the Height=270 and Width=600 for your user control. This way, the outer grid fills all the available space in the window, and the lower right cell has scroll bars.

Resources