I have a popup that opens when we click on the toggle button. I have written a converter such that popup closes whenever we click on toggle button again or when we click anywhere other than the popup.
the XAML code is this
<ToggleButton x:Name="m_XYProfileBtn" Content="Profiles" Height="24" Style="{DynamicResource StatusFlatToggle}"
Visibility="{Binding IsToggleStatusVisibility}" IsChecked="{Binding IsPopUpOpen}" />
<Popup Margin="5" Name="ProfilePopup" HorizontalAlignment="Center" VerticalAlignment="Center"
Width="400" Height="500" AllowsTransparency="True"
IsOpen="{Binding IsPopUpOpen}"
Focusable="False"
PopupAnimation="Slide"
Placement="Top"
VerticalOffset="-4"
HorizontalOffset="2"
>
<Popup.StaysOpen>
<MultiBinding Converter="{StaticResource MultiBinding_StayOpen}">
<Binding ElementName="m_XYProfileBtn" Path="IsMouseOver"/>
<Binding ElementName="Pin" Path="IsChecked" />
</MultiBinding>
</Popup.StaysOpen>
<Border BorderThickness="2" BorderBrush="Gray" Background="White" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.05*" />
<RowDefinition Height="0.95*" />
</Grid.RowDefinitions>
<CheckBox Name="Pin" Content="Pin" Style ="{StaticResource PinBox}" HorizontalAlignment="Right"/>
<Grid Name="xProfileGrid" Grid.Row="1" />
</Grid>
</Border>
and the C# converter code is this
public class MultiBinding_StayOpen : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool toggleIsMouseOver;
bool pinIsChecked;
//System.Threading.Thread.Sleep(3000);
toggleIsMouseOver = System.Convert.ToBoolean(values[0]);
pinIsChecked = System.Convert.ToBoolean(values[1]);
if (pinIsChecked == true)
return true;
else if (toggleIsMouseOver == true)
return true;
else if (toggleIsMouseOver == false)
{
System.Threading.Thread.Sleep(300);
return false;
}
return true;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
This works fine but the first time you click on the toggle button, popup opens up again in place of closing. After that it works perfectly. Any suggestion how I can fix this?
Related
Goal: To align combobox popup to bottom Left. Kindly check image below for reference:
What i tried?: I tried playing with Placement property of PART_Popup. If i set Placement="Bottom", the Popup is rendering from Bottom right. Check this image below:
Also, in VS Designer it is showing correctly:
ComboBox PART_Popup:
<Popup x:Name="PART_Popup"
AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom"
MinWidth="170">
<themes:SystemDropShadowChrome x:Name="shadow" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=templateRoot}">
<Border x:Name="dropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{StaticResource ComboBox.Static.Background}"
CornerRadius="3">
<ScrollViewer x:Name="DropDownScrollViewer" CanContentScroll="False">
<Grid x:Name="grid" RenderOptions.ClearTypeHint="Enabled">
<Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
<Rectangle x:Name="opaqueRect" Fill="{Binding Background, ElementName=dropDownBorder}"
Height="{Binding ActualHeight, ElementName=dropDownBorder}" Width="{Binding ActualWidth, ElementName=dropDownBorder}"/>
</Canvas>
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="16"/>
</Grid>
</ScrollViewer>
</Border>
</themes:SystemDropShadowChrome>
</Popup>
XAML:
<ComboBox
HorizontalAlignment="Left"
VerticalAlignment="Center"
SelectedIndex="0"
Margin="50,0"
Style="{StaticResource FlatComboBoxStyle2}">
<ComboBoxItem Content="Recent"/>
<ComboBoxItem Content="Alphabetical"/>
</ComboBox>
I am looking for XAML code solution only. Thanks.
I fixed it by adding a converter in App.xaml.cs:
public class PositiveToNegativeConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (double) value > 0 ? 0 - (double) value : 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
And define it in my ComboBoxTemplate:
<PositiveToNegativeConverter x:Key="PositiveToNegativeConverter" />
And call it like this in Popup's HorizontalOffest:
HorizontalOffset="{Binding ActualWidth, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource PositiveToNegativeConverter}}"
I hope this helps out anyone looking for solution.
I had the same issue, and after following several thread here (all my XAML trial failed, to brief up, Popup.Placement = [whatever] didn't change anything on run) I ended up with the following "solution".
Not pretty, so if you knew more elegant way I'm open.
So I named my ComboBox and Add a event handler (via XAML) on DropDownOpen (this is the dirty side imo) where I force my Popup.Placement to RelativePoint and set a VerticalOffset to my ComboBox.ActualHeight.
Here is the XAML code :
<ComboBox Name="NIC_CmbBox" HorizontalAlignment="Stretch" DropDownOpened="NIC_CmbBox_DropDownOpened">
C# :
private Popup _comboBoxPopup;
private void NIC_CmbBox_DropDownOpened(object sender, EventArgs e)
{
ComboPopupPlacement();
}
public Popup ComboBoxPopup {
get
{
if(_comboBoxPopup == null)
{
//try to get it
if(NIC_CmbBox != null)
_comboBoxPopup = (Popup)NIC_CmbBox.Template.FindName("PART_Popup", NIC_CmbBox);
}
return _comboBoxPopup;
}
set => _comboBoxPopup = value; }
public void ComboPopupPlacement()
{
//If placement haven't already be done
if (ComboBoxPopup != null && _comboBoxPopup.Placement != PlacementMode.RelativePoint)
{
_comboBoxPopup.Placement = PlacementMode.RelativePoint;
_comboBoxPopup.VerticalOffset = NIC_CmbBox.ActualHeight;
}
}
I am new on silverlight development. During my activity i have encountered an error which is i mentioned on the title of this post. My main purpose is popup date picker when clicking button.
<ToggleButton x:Name="TogglePopupButton" HorizontalAlignment="Right" Height="26" VerticalAlignment="Center" Grid.Column="1" Style="{StaticResource ToolIconToggleButtonStyle}" Width="26"
IsEnabled="{Binding ElementName=ToggledPopup, Path=IsOpen,Converter={StaticResource BoolToInvertedBoolConverter}}">
this is .xaml
<UserControl
<xmlns:local="clr-namespace:US.Payment.Web.Modules.PaymentMachine.Utils">
<UserControl.Resources>
<US_Payment_Web_Converters:GroupRowHeaderVisibilityConverter x:Key="GroupRowHeaderVisibilityConverter"/>
<viewModel:ImportUSPViewModel x:Name="ViewModel"/>
<local:AmountValuesConverter x:Name="AmountConverter"/>
<local:BackgroundConverter x:Key="BackgroundConverter" />
<local:BoolToInvertedBoolConverter x:Key="BoolToInvertedBoolConverter " />
<Style x:Key="CalendarDayButtonStyle1" TargetType="prim:CalendarDayButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="prim:CalendarDayButton">
<Grid Background= "{Binding Converter={StaticResource BackgroundConverter}, Path=Date}">
<ContentControl x:Name="Content" Margin="5,1,5,1" Content="{TemplateBinding Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
This is BoolToInvertedBoolConverter.cs file
public class BoolToInvertedBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is bool)
{
bool boolValue = (bool)value;
return !boolValue;
}
else
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException("ConvertBack() of BoolToInvertedBoolConverter is not implemented");
}
}
The problem is, you accidentally put a space character at the and of the x:Key value when declaring your resource. Remove that character and it will work.
x:Key="BoolToInvertedBoolConverter "-> has space at the end but should be
x:Key="BoolToInvertedBoolConverter" -> without space.
Here is xaml code that builds up a tree with horizontal nodes for me.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BlogSample">
<local:HorzLineConv x:Key="horzLineConv"/>
<local:VertLineConv x:Key="vertLineConv"/>
<Style TargetType="TreeViewItem" x:Key="GraphStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid> <!-- Main Grid-->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- Horizontal line-->
<RowDefinition Height="Auto"/>
<!--The top row contains the item's content.-->
<RowDefinition Height="Auto" />
<!-- Item presenter(children) -->
</Grid.RowDefinitions>
<Grid Grid.Row="0"> <!-- Horizontal line grid -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Horizontal line to the left -->
<Rectangle Grid.Column="0" HorizontalAlignment="Stretch"
Stroke="Black" SnapsToDevicePixels="true">
<Rectangle.Height>
<Binding Mode="OneWay"
Converter="{StaticResource horzLineConv}"
ConverterParameter="left"
RelativeSource="{RelativeSource
AncestorLevel=1,
AncestorType={x:Type TreeViewItem}}"/>
</Rectangle.Height>
</Rectangle>
<!-- Horizontal line to the right -->
<Rectangle Grid.Column="1" HorizontalAlignment="Stretch"
Stroke="Black"
SnapsToDevicePixels="true">
<Rectangle.Height>
<Binding Mode="OneWay"
Converter="{StaticResource horzLineConv}"
ConverterParameter="right"
RelativeSource="{RelativeSource
AncestorLevel=1,
AncestorType={x:Type TreeViewItem}}"/>
</Rectangle.Height>
</Rectangle>
</Grid> <!-- End of Horizontal line grid -->
<Grid Grid.Row="1"> <!-- Header grid -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/><!-- Vert. line above node -->
<RowDefinition Height="*"/> <!-- Header -->
<RowDefinition Height="Auto"/><!-- Vert line below node -->
</Grid.RowDefinitions>
<!-- Vertical line above node -->
<Rectangle Grid.Row="0"
Height="10" Stroke="Black" SnapsToDevicePixels="true">
<Rectangle.Width>
<Binding Mode="OneWay"
Converter="{StaticResource vertLineConv}"
ConverterParameter="top"
RelativeSource=
"{RelativeSource AncestorLevel=1,
AncestorType={x:Type TreeViewItem}}"/>
</Rectangle.Width>
</Rectangle>
<!-- Header -->
<ContentPresenter Grid.Row="1" ContentSource="Header"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
<!-- Vertical line below node -->
<Rectangle Grid.Row="2" Height="10" Stroke="Black"
SnapsToDevicePixels="true">
<Rectangle.Width>
<Binding Mode="OneWay"
Converter="{StaticResource vertLineConv}"
ConverterParameter="bottom"
RelativeSource=
"{RelativeSource AncestorLevel=1,
AncestorType={x:Type TreeViewItem}}"/>
</Rectangle.Width>
</Rectangle>
</Grid> <!-- End of Header grid -->
<ItemsPresenter Grid.Row="2"/> <!-- Children -->
</Grid> <!-- End of Main grid -->
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel
HorizontalAlignment="Center"
IsItemsHost="True"
Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="local:TreeViewItemBehavior.IsBroughtIntoViewWhenSelected" Value="True" />
</Style>
</ResourceDictionary>
It has a couple of attached convertors with it that help with the node linking lines' creation. Also there is attached behavior that brings into view (i.e. scrolls into view) a node when it is clicked.
Here is the code behind:
namespace BlogSample
{
public class HorzLineConv : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
TreeViewItem item = (TreeViewItem)value;
ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(item);
int index = ic.ItemContainerGenerator.IndexFromContainer(item);
if ((string)parameter == "left")
{
if (index == 0) // Either left most or single item
return (int)0;
else
return (int)1;
}
else // assume "right"
{
if (index == ic.Items.Count - 1) // Either right most or single item
return (int)0;
else
return (int)1;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class VertLineConv : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
TreeViewItem item = (TreeViewItem)value;
ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(item);
int index = ic.ItemContainerGenerator.IndexFromContainer(item);
if ((string)parameter == "top")
{
if (ic is TreeView)
return 0;
else
return 1;
}
else // assume "bottom"
{
if (item.HasItems == false)
return 0;
else
return 1;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
public static class TreeViewItemBehavior
{
#region IsBroughtIntoViewWhenSelected
public static bool GetIsBroughtIntoViewWhenSelected(TreeViewItem treeViewItem)
{
return (bool)treeViewItem.GetValue(IsBroughtIntoViewWhenSelectedProperty);
}
public static void SetIsBroughtIntoViewWhenSelected(TreeViewItem treeViewItem, bool value)
{
treeViewItem.SetValue(IsBroughtIntoViewWhenSelectedProperty, value);
}
public static readonly DependencyProperty IsBroughtIntoViewWhenSelectedProperty =
DependencyProperty.RegisterAttached(
"IsBroughtIntoViewWhenSelected",
typeof(bool),
typeof(TreeViewItemBehavior),
new UIPropertyMetadata(false, OnIsBroughtIntoViewWhenSelectedChanged));
static void OnIsBroughtIntoViewWhenSelectedChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
TreeViewItem item = depObj as TreeViewItem;
if (item == null)
return;
if (e.NewValue is bool == false)
return;
if ((bool)e.NewValue)
item.Selected += OnTreeViewItemSelected;
else
item.Selected -= OnTreeViewItemSelected;
}
static void OnTreeViewItemSelected(object sender, RoutedEventArgs e)
{
// Only react to the Selected event raised by the TreeViewItem
// whose IsSelected property was modified. Ignore all ancestors
// who are merely reporting that a descendant's Selected fired.
if (!Object.ReferenceEquals(sender, e.OriginalSource))
return;
//Point relativePoint = (sender as TreeViewItem).TransformToAncestor(Application.Current.MainWindow)
// .Transform(new Point(0, 0));
TreeViewItem item = e.OriginalSource as TreeViewItem;
if (item != null)
item.BringIntoView();
}
#endregion // IsBroughtIntoViewWhenSelected
}
}
What I want to do is:
Make just the parent of leaf nodes scroll horizontall into view when there is a scroll change. So that even if out of all leaf nodes (of a parent) if only 1 leaf node is visible then the parent is still visible. If all the leaf nodes of a parent go out of view then that parent node must also go out of view.
Please guide me hpow to do this. Can it be done using attached behavior? Can it be done easily using Blend?
I have a canvas and when a user right clicks on it, a context menu appears. I also have a checkbox, and when that box is checked, I DON'T want the context menu to appear. The reason for this is that, when the checkbox is checked, the first two right clicks from the user will drop ellipses at the two points of the right clicks. Right now though, the context menu will popup on those two right clicks. Here's the relative code:
<Window x:Class="Testproj.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Testproj"
xmlns:localConverters="clr-namespace:Testproj"
x:Name="this"
Height="650" Width="1091"
Loaded="this_Loaded"
Closing="this_Closing">
<Window.Resources>
<local:BoolToVisibilityConverter x:Key="converter"/>
</Window.Resources>
<Grid Height="Auto">
<Grid.Resources>
<local:NullToVisibilityConverter x:Key="nullToVisibilityConverter" />
</Grid.Resources>
<Grid VerticalAlignment="Top">
<DockPanel>
<CheckBox x:Name="scaleBox" Content="Scale" IsChecked="False" Checked="scaleischecked"/>
</Menu>
</DockPanel>
</Grid>
<Viewbox Margin="0,23,0,157" x:Name="viewbox1" ClipToBounds="True">
<Canvas Margin="0,21,0,12" x:Name="canvas1" ClipToBounds="True" RenderOptions.BitmapScalingMode="HighQuality" MouseWheel="Canvas_Zoom" MouseRightButtonDown="get_MousePosition" HorizontalAlignment="Left" Width="3138" Height="1260">
<Canvas.RenderTransform>
<MatrixTransform x:Name="mt"/>
</Canvas.RenderTransform>
<Canvas.ContextMenu>
<ContextMenu Name="nodeContextMenu" Visibility="{StaticResource converter}" >
<MenuItem x:Name="test1" IsCheckable="False" Header="test1" Click="WaypointMenuItem_Click" >
</MenuItem>
<MenuItem x:Name="test2" IsCheckable="False" Header="test2" Click="KnownObjectMenuItem_Click" >
</MenuItem>
</ContextMenu>
</Canvas.ContextMenu>
</Canvas>
</Viewbox>
</Grid>
</Window>
and the code behind for the right-click on canvas:
private void get_MousePosition(object sender, MouseButtonEventArgs e)
{
if (scaleBox.IsChecked == true)
{
get_points(sender, e);
}
}
I've tried messing around with the isOpen property of the context-menu, but it always open on right click regardless if it's set to true or false.
Attempt at converter below. If this is correct, what is the proper way to bind the checkbox and contextmenu using this?
namespace Testproj
{
public class BoolToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Visibility visibility = Visibility.Collapsed;
if (value != null)
{
visibility = (bool)value ? Visibility.Collapsed : Visibility.Visible;
}
return visibility;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
I would implement a ValueConverter or MultiValueConverter and then bind to the checkbox using the converter to dictate the state (i.e. enabled/disabled) of the contextmenu.
<Canvas.ContextMenu>
<ContextMenu Name="contextmenu1" Visibility="{Binding ElementName=scaleBox, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" >
<MenuItem x:Name="item1" IsCheckable="False" Header="item2" />
<MenuItem x:Name="item2" IsCheckable="False" Header="item1" />
</ContextMenu>
Here's the way I figured out how to do it since I couldn't get the converter to work properly:
Set the ContextMenuService.IsEnabled property to false in the canvas. Then, in the code behind, set nodeContextMenu.IsOpen = true when the scalebox is not checked. This seems to do the trick.
<Canvas Margin="0,21,0,12" x:Name="canvas1" ContextMenuService.IsEnabled="False" />
if (scaleBox.IsChecked == true)
{
get_Scaling(sender, e);
}
else
{
nodeContextMenu.IsOpen = true;
}
This is C# WPF and xaml. I have main window, and I have two graphs that share this window. They are vertically arranged. They both have same width as the main window. However, I want the first graph to fill the entire window (except for some margin on the top of the window) when the second one is collapsed, and I want them to share the height (each with Height = (Height of Window)/2 ) when both are visible.
Here is what I tried in xaml, not successful though:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<d3:ChartPlotter Grid.Row="0" Name ="timeDomainPlotter" >
</d3:ChartPlotter>
<d3:ChartPlotter Grid.Row="1" Name ="freqDomainPlotter" >
</d3:ChartPlotter>
</Grid>
The first window does not take over the second window's space when the second one is Visibility.Collapsed.
How should I do this? Thanks.
Update:
Converter code in pop up window where there are two graphs:
public class VisibilityToHeightConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
GridLength height = new GridLength();
var visiblity = (Visibility)value;
switch (visiblity)
{
case Visibility.Collapsed:
height = new GridLength(0, GridUnitType.Auto);
break;
case Visibility.Visible:
height = new GridLength(1, GridUnitType.Star);
break;
case Visibility.Hidden:
height = new GridLength(0, GridUnitType.Auto);
break;
}
return height;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
/// <summary>
/// Interaction logic for SignalStatsDisplay.xaml
/// </summary>
public partial class SignalStatsDisplay : Window
{
xaml for pop up window:
<Window x:Class="FileWatcherCaller.View.SignalStatsDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0"
xmlns:local="clr-namespace:FileWatcherCaller.View"
Title="Real Time Signal Display" Height="409" Width="1200">
<Window.Resources>
<local:VisibilityToHeightConverter x:Key="VisToHeightConv"/>
</Window.Resources>
<Grid>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<CheckBox Height="16" HorizontalAlignment="Left" Name="pixVal" VerticalAlignment="Top" Width="120" Checked="checkBox1_Checked">Pixel Value</CheckBox>
<CheckBox Height="16" HorizontalAlignment="Left" Name="roiMean" VerticalAlignment="Top" Width="120">ROI Mean</CheckBox>
<CheckBox Height="16" HorizontalAlignment="Left" Name="roiStd" VerticalAlignment="Top" Width="120" Checked="roiStd_Checked">ROI Std</CheckBox>
</StackPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding ElementName=timeDomainPlotter, Path=Visibility, Converter={StaticResource VisToHeightConv}}" Name="RowOne" />
<RowDefinition Height="{Binding ElementName=freqDomainPlotter, Path=Visibility, Converter={StaticResource VisToHeightConv}}" Name="RowTwo" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<d3:ChartPlotter Grid.Row="0" Name ="timeDomainPlotter" >
</d3:ChartPlotter>
<d3:ChartPlotter Grid.Row="1" Name ="freqDomainPlotter" >
</d3:ChartPlotter>
</Grid>
</StackPanel>
</Grid>
</Window>
In main window, how the Visibility of two graphs are initialized:
public void StartWatch()
{
if (_fileWatcher != null)
{
_fileWatcher.Dispose();
_fileWatcher = null;
}
if (InitWatcher())
{
this._fileWatcher.Start();
this.ButtonStart.IsEnabled = false;
this.ButtonStop.IsEnabled = true;
}
_signalDisplay = new SignalStatsDisplay();
if (_signalDisplay.Visibility != Visibility.Visible)
{
_signalDisplay.Show();
_signalDisplay.timeDomainPlotter.Visibility = Visibility.Visible;
_signalDisplay.freqDomainPlotter.Visibility = Visibility.Collapsed;
}
}
For Kevin's sulution, I have the xaml for the pop up window:
<Window x:Class="FileWatcherCaller.View.SignalStatsDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0"
Title="Real Time Signal Display" Height="409" Width="1200">
<Grid>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<CheckBox Height="16" HorizontalAlignment="Left" Name="pixVal" VerticalAlignment="Top" Width="120" Checked="checkBox1_Checked">Pixel Value</CheckBox>
<CheckBox Height="16" HorizontalAlignment="Left" Name="roiMean" VerticalAlignment="Top" Width="120">ROI Mean</CheckBox>
<CheckBox Height="16" HorizontalAlignment="Left" Name="roiStd" VerticalAlignment="Top" Width="120" Checked="roiStd_Checked">ROI Std</CheckBox>
</StackPanel>
<UniformGrid Columns="1">
<d3:ChartPlotter Name ="timeDomainPlotter" >
</d3:ChartPlotter>
<d3:ChartPlotter Name ="freqDomainPlotter" >
</d3:ChartPlotter>
</UniformGrid>
</StackPanel>
</Grid>
</Window>
But still, it is not maximize the top D3 graph as expected. It is still takes only half of the window. Anything I should do in the behind code?
<Window x:Class="FileWatcherCaller.View.SignalStatsDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0"
Title="Real Time Signal Display" Height="409" Width="1200">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
<CheckBox Height="16" HorizontalAlignment="Left" Name="pixVal" VerticalAlignment="Top" Width="120" Checked="checkBox1_Checked">Pixel Value</CheckBox>
<CheckBox Height="16" HorizontalAlignment="Left" Name="roiMean" VerticalAlignment="Top" Width="120">ROI Mean</CheckBox>
<CheckBox Height="16" HorizontalAlignment="Left" Name="roiStd" VerticalAlignment="Top" Width="120" Checked="roiStd_Checked">ROI Std</CheckBox>
</StackPanel>
<UniformGrid Columns="1" Grid.Row="1">
<d3:ChartPlotter Name ="timeDomainPlotter" >
</d3:ChartPlotter>
<d3:ChartPlotter Name ="freqDomainPlotter" >
</d3:ChartPlotter>
</UniformGrid>
</Grid>
</Window>
UniformGrid works the way you're looking for (as long as you don't want the user to resize the two sections)
<UniformGrid Columns="1">
<TextBox Visibility="Collapsed">Hello</TextBox>
<TextBox Visibility="Visible">Goodbye</TextBox>
</UniformGrid>
For something more flexible, I think you're going to have to write some code.
Here is an example app that has your desired behavior:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:VisibilityToHeightConverter x:Key="VisToHeightConv"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding ElementName=rctTop, Path=Visibility, Converter={StaticResource VisToHeightConv}}" Name="RowOne" />
<RowDefinition Height="{Binding ElementName=rctBottom, Path=Visibility, Converter={StaticResource VisToHeightConv}}" Name="RowTwo" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Rectangle Fill="Black" Name="rctTop" Grid.Row="0"/>
<Rectangle Fill="Red" Name="rctBottom" Grid.Row="1"/>
</Grid>
</Window>
Code Behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class VisibilityToHeightConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
GridLength height = new GridLength();
var visiblity = (Visibility)value;
switch(visiblity)
{
case Visibility.Collapsed:
height = new GridLength(0, GridUnitType.Auto);
break;
case Visibility.Visible:
height = new GridLength(1, GridUnitType.Star);
break;
case Visibility.Hidden:
height = new GridLength(0, GridUnitType.Auto);
break;
}
return height;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Let us know if any part of this code is unfamiliar (value converters, binding) and we'll provide an explanation.