WPF: Hide control in window from child page - c#

I am using a frame to navigate through multiple pages. The window is a wrapper of sorts as it displays the header with the titles to the pages and I have the footer with the navigation controls (back, home, forward). However the first page to load is the login screen so I would like to hide/modify the elements in the header and footer. These items are a part of the main window and the pages are child elements of the main window. How would I access the main windows elements from the child pages? I've attempted to name the elements and using the FindName method from the child pages but it is not working. I have the home button (HomeButtonBorder) collapsed originally and would like to make it visible once the user has successfully logged in.
Here is the MainWindow Code
<Grid>
<!-- HEADER -->
<Grid x:Name="HeaderGrid" Style="{StaticResource HeaderGridStyle}">
<Rectangle x:Name="HeaderRectangle" Style="{StaticResource HeaderRectangleStyle}" />
<Image x:Name="HeaderLogo" Style="{StaticResource HeaderLogoStyle}" />
<!-- PAGE HEADER -->
<!-- TITLE -->
<Grid x:Name="HeaderTitleGrid" Style="{StaticResource HeaderTitleGridStyle}" >
<Label x:Name="HeaderTitleLabel"
Style="{StaticResource HeaderTitleStyle}"
Content="{Binding Path=Content.Title, ElementName=MainFrame}" />
<!-- END HEADER -->
<!-- MAIN -->
<Frame x:Name="MainFrame" NavigationUIVisibility="Hidden"/>
<!-- END MAIN -->
<!--NAVIGATION -->
<!-- Back Button -->
<Button Content="«" Click="Nav_BackButton_OnClick" HorizontalAlignment="Left"
Visibility="{Binding Path=CanGoBack, ElementName=MainFrame, Converter={StaticResource BoolToVis}}"
Style="{StaticResource NavigationButtonStyle}" />
<!-- Home Button -->
<Border x:Name="HomeButtonBorder" Style="{StaticResource HomeBorderStyle}" MouseUp="Nav_HomeButton_OnClick">
<Image x:Name="HomeImage" Source="/Images/HomeButton_250x250.PNG" Width="100" />
</Border>
<!-- Forward Button -->
<Button Content="»" Click="Nav_ForwardButton_OnClick" HorizontalAlignment="Right"
Visibility="{Binding Path=CanGoForward, ElementName=MainFrame, Converter={StaticResource BoolToVis}}"
Style="{StaticResource NavigationButtonStyle}"/>
</Grid>
Here is the Login Page code that is not successful (It runs on LoginPage loaded)
public _0_LoginPage()
{
InitializeComponent();
}
private void LoginLoad(object sender, RoutedEventArgs e)
{
var homeButton = FindName("HomeButtonBorder") as Border;
var homeImage = FindName("HomeImage") as Image;
if (homeButton == null || homeImage == null) return;
homeButton.Visibility = Visibility.Visible;
homeImage.Visibility = Visibility.Visible;
}

I tried to use a interface which will deal with hiding the Home button. Refer the below code.
MainWindow.xaml
<Window x:Class="SQ15Mar2015_Learning.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<Grid>
<StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="Login" Click="Button_Click"></Button>
<Button Content="Home" Visibility="{Binding HomeVisibility, RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=Window}}"/>
</StackPanel>
<Frame x:Name="frm"></Frame>
</StackPanel>
</Grid>
MainWindow.cs
public partial class Window2 : Window, IHomeVisibility,INotifyPropertyChanged
{
public Window2()
{
InitializeComponent();
HomeVisibility = Visibility.Collapsed;
}
private Visibility homeVisibility;
public Visibility HomeVisibility
{
get { return homeVisibility; }
set { homeVisibility = value; OnPropertyChanged("HomeVisibility"); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
frm.Navigate(new Login(this));
}
}
Interface
public interface IHomeVisibility
{
Visibility HomeVisibility { get; set; }
}
Login.xaml.cs
public partial class Login : Page
{
public Login(IHomeVisibility homeBtnVisiblity)
{
InitializeComponent();
homeBtnVisiblity.HomeVisibility = Visibility.Visible;
}
}
There are many ways of doing dealing it. I strongly suggest you to go through MVVM.

Related

How to use popup within a tabitem to show that tab contents is loading in wpf mvvm?

I'm using tabitem which contains a popup to show that data is loading from API .
The problem is the popup shows over the window, and it disappears whenever another tab is selected even though the data is still loading.
Is it possible for popup to be shown within the tab like other controls? and keep doing what it's doing whether the containing tab is selected or not?
what control do you suggest to use instead of popup if it's not the right one for this case?
Here is an example to explain:
ViewModel:
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
private bool showPopUp;
public bool ShowPopUp
{
get { return showPopUp; }
set
{
showPopUp = value;
OnPropertyChanged(nameof(ShowPopUp));
}
}
}
Code behind:
public partial class MainWindow : Window
{
MainWindowViewModel model = new MainWindowViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = model;
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
//loading data
model.ShowPopUp = true;
await Task.Delay(100000);
model.ShowPopUp = false;
}
}
XAML:
<TabControl x:Name="tc">
<TabItem x:Name="tab1" Header="Tab1">
<TabItem.Content>
<Grid>
<Popup
Name="popUp1"
StaysOpen="True"
IsOpen="{Binding ShowPopUp, Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}"
AllowDrop="True" Placement="Center"
Height="90" Width="135">
<Grid Background="LightGray">
<TextBlock Text="Loading ..." Margin="32" FontSize="16" />
</Grid>
</Popup>
<Button Height="30" Width="100" Content="Show popup" Click="Button_Click"/>
</Grid>
</TabItem.Content>
</TabItem>
<TabItem
x:Name="tab2"
Header="Tab2">
</TabItem>
</TabControl>

Target version 16299 versus 17134 Pivot/Content presenter behavior differences

I can't figure out what has changed between these two versions to display this behavior, but I would like to gather some insight on what might be happening from some different point of views. I have a Top level menu, containing a Sub level menu in which this display the actual content.
I have a MainPage with a pivot menu. The MainPages pivot contains within its ItemTemplate a Page named "Tab".
Each MainPage pivot selection has its own instance of "Tab"
Tab contains another Pivot menu. In the "Tab" pivot menu ItemTemplate, I have a ContentPresenter control thats bound to a collection item of type UserControl named "SubTabContent".
In 16299 each instance of the SubTabContent load event is fired when the sub tab is selected.
In 17134, all SubTabContent load events are fired without the sub tab being selected.
This is what i'm trying to control, but cannot find why this is happening. Is it the ContentPresenter? Or the pivot, or the architecture?
Steps to reproduce this. Create two Blank UWP Projects. Target one with 16299, and another with 17134.
Use the code/steps below for both apps. Set a break point in the load event of the SubTabContent user control, and you will see the difference between the two apps in how they load.
I need the sublevel content to only load when i select the tab for it. I don't want it to load outside of that. I'm currently in 16299 which works fine, and would like to go up to 17134 for newer feature usage. but cannot since this load behavior.
In the MainPage
<Page
x:Class="_17134PivotExample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:_17134PivotExample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<ScrollViewer BorderBrush="Blue" BorderThickness="3">
<Pivot ItemsSource="{x:Bind menuItems}">
<Pivot.HeaderTemplate>
<DataTemplate x:DataType="local:MenuItem">
<TextBlock Text="{x:Bind Header}"/>
</DataTemplate>
</Pivot.HeaderTemplate>
<Pivot.ItemTemplate>
<DataTemplate x:DataType="local:MenuItem">
<local:Tab/>
</DataTemplate>
</Pivot.ItemTemplate>
</Pivot>
</ScrollViewer>
</StackPanel>
</Page>
public sealed partial class MainPage : Page
{
public ObservableCollection<MenuItem> menuItems { get; set; }
public MainPage()
{
this.InitializeComponent();
menuItems = new ObservableCollection<MenuItem>();
for (int i = 0; i < 6; i++)
{
menuItems.Add(new MenuItem
{
Header = "Menu Tab + {i++}",
Content = new Tab()
});
}
}
}
Add one class in each app
public class MenuItem
{
public string Header { get; set; }
public UserControl Content { get; set; }
}
Add a page named "Tab"
<Page
x:Class="_17134PivotExample.Tab"
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:local="using:_17134PivotExample"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Grid>
<ScrollViewer BorderBrush="Black"
BorderThickness="3">
<Pivot
ItemsSource="{x:Bind menuItems}">
<Pivot.HeaderTemplate>
<DataTemplate x:DataType="local:MenuItem">
<TextBlock Text="{x:Bind Header}" />
</DataTemplate>
</Pivot.HeaderTemplate>
<Pivot.ItemTemplate>
<DataTemplate x:DataType="local:MenuItem">
<ScrollViewer>
<ContentPresenter Content="{x:Bind Content}" />
</ScrollViewer>
</DataTemplate>
</Pivot.ItemTemplate>
</Pivot>
</ScrollViewer>
</Grid>
</Page>
public sealed partial class Tab : Page
{
public ObservableCollection<MenuItem> menuItems { get; set; }
public Tab()
{
this.InitializeComponent();
menuItems = new ObservableCollection<MenuItem>();
for (int i = 0; i < 6; i++)
{
menuItems.Add(new MenuItem
{
Header = "Sub Menu Tab" + i++,
Content = new SubTabContent()
});
}
this.Loaded += Tab_Loaded;
}
private void Tab_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
int blah = 1;
}
}
Add a UserControl named SubTabContent
<UserControl
x:Class="_17134PivotExample.SubTabContent"
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:local="using:_17134PivotExample"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="Black"
mc:Ignorable="d">
<StackPanel>
<TextBlock Text="New Page" />
<TextBlock Text="New Page" />
<TextBlock Text="New Page" />
<TextBlock Text="New Page" />
<TextBlock Text="New Page" />
<TextBlock Text="New Page" />
<TextBlock Text="New Page" />
<TextBlock Text="New Page" />
<TextBlock Text="New Page" />
<TextBlock Text="New Page" />
</StackPanel>
</UserControl>
public sealed partial class SubTabContent : UserControl
{
public SubTabContent()
{
this.InitializeComponent();
this.Loaded += SubTabContent_Loaded;
}
private void SubTabContent_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
int i = 0;
Debug.WriteLine("Loaded" + i++);
}
}

Capture mouse click inside UserControl

I have created an UserControl which holds several labels. On the other side, I have a window (simple grid) which creates 6 instances of UserControl and places them in a single row.
My question is: how to fire up some action when user clicks on userControl (any part of it)?
I've tried to add MouseDown event handler inside UserControl cs file, and inside parent window during UserControl instance creation, but this doesn't have any effect. I've also tried adding PreviewMouseLeftButtonDown, MouseEnter, MouseLeftButtonDownButton but nothing of these worked.
This is part of parent window:
public BuyerSellerMonitorGridWindow()
{
InitializeComponent();
for (int i = 0; i < 6; i++)
{
// Add new column to grid
this.grdBuyer.ColumnDefinitions.Add(new ColumnDefinition());
// Create and add new transaction
UserControl uc = new UserControl();
uc.PreviewMouseLeftButtonDown += uc_MouseDown;
System.Windows.Controls.Grid.SetRow(uc, 0);
System.Windows.Controls.Grid.SetColumn(uc, i);
this.grdBuyer.Children.Add(uc);
}
}
This is UserControl:
public partial class Transaction: UserControl
{
public Transaction()
{
InitializeComponent();
}
private void TransactionClicked()
{
Console.WriteLine("test");
}
}
And this is xaml:
<UserControl x:Class="AssetStudio.Dialogs.Transaction"
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"
xmlns:local="clr-namespace:AssetStudio.Dialogs"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel x:Name="frameTransaction">
<Label x:Name="lblClientName" Content="Client A" Height="35"/>
<Label x:Name="lblDate" Content="2017/05/01"/>
<Grid Height="34">
<Label x:Name="label" Content="Curr Px" HorizontalAlignment="Left" Width="150"/>
<Label x:Name="lblCurrentPrice" Content="Label" Margin="150,0,0,0"/>
</Grid>
<Grid Height="34">
<Label x:Name="label2" Content="Trade Px" HorizontalAlignment="Left" Width="150"/>
<Label x:Name="lblTradePrice" Content="Label" Margin="150,0,0,0"/>
</Grid>
<Grid Height="34">
<Label x:Name="label4" Content="Qty Done" HorizontalAlignment="Left" Width="150"/>
<Label x:Name="lblQuantityDone" Content="Label" Margin="150,0,0,0"/>
</Grid>
<Grid Height="34">
<Label x:Name="label6" Content="Size" HorizontalAlignment="Left" Width="150"/>
<Label x:Name="lblSize" Content="Label" Margin="150,0,0,0"/>
</Grid>
<Grid Height="34">
<Label x:Name="label8" Content="Stk Px" HorizontalAlignment="Left" Width="150"/>
<Label x:Name="lblStockPrice" Content="Label" Margin="150,0,0,0"/>
</Grid>
<Grid Height="34">
<Label x:Name="label10" Content="Delta" HorizontalAlignment="Left" Width="150"/>
<Label x:Name="lblDelta" Content="Label" Margin="150,0,0,0"/>
</Grid>
</StackPanel>
</UserControl>
You can do something like this:
in your UserControl:
include namespaces:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
and add CallMethodAction
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<ei:CallMethodAction MethodName="UserControlClicked"
TargetObject="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
TargetObject="{Binding}" tells you that this UserControlClicked method needs to be in your ViewModel that is DataContext of that UserControl.
where UserControlClicked is public method that you call when MouseLeftButtonDown is made on that control.
this is my UserControlViewModel just to show purpose,and to test.
public class UserControlViewModel : INotifyPropertyChanged
{
public UserControlViewModel()
{
Text = "Started!";
}
private string _text;
public string Text
{
get { return _text; }
set
{
_text = value;
OnPropertyChanged();
}
}
public void UserControlClicked()
{
Text = "Clicked!";
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Inside MainWindow i have instanced couple of this UserControl-s:
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel>
<local:UserControl1 />
<local:UserControl1 />
<local:UserControl1 />
<local:UserControl1 />
<local:UserControl1 />
</StackPanel>
</Grid>
And this seems to be working as expected. UserControl that has beed clicked changed label content from Started! to Clicked!.
EDIT: Check this on how to add CallMethodAction via Blend:
CallMethodAction

Xaml UWP buttons hide/show not working using INotifyPropertyChanged

When i press the button the appbarbutton and slider doesnt hide.
When i debug i can confirm the "Collapse or Visible" is been notified.
Not sure what mistake i do. Please help to fix the issue.
I am building for Universal Windows Platform (UWP) for xbox one.
<Page
x:Class="AvProStreaming.MainPage"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AvProStreaming"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="RosyBrown">
<SwapChainPanel x:Name="DXSwapChainPanel">
<Grid x:Name="ExtendedSplashGrid" Background="#FFFFFF">
<Image x:Name="ExtendedSplashImage" Source="Assets/SplashScreen.png" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
<Slider x:Name="slider" Background="Cyan" HorizontalAlignment="Stretch" Margin="10,444,10,0" VerticalAlignment="Top" Height="46"
Visibility="{Binding IsHide}" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="150" >
<AppBarButton Foreground="Cyan" Icon="Back" Name="Backward" Label="Back" Click="MenuItem_Selected"
Visibility="{Binding IsHide}" Margin="30"/>
<AppBarButton Foreground="Cyan" Icon="Play" Name="Play" Label="Play" Click="MenuItem_Selected"
Visibility="Collapsed" Margin="30"/>
<AppBarButton Foreground="Cyan" Icon="Pause" Name="Pause" Label="Pause" Click="MenuItem_Selected"
Visibility="{Binding IsHide}" Margin="30"/>
<AppBarButton Foreground="Cyan" Icon="Forward" x:Name="Forward" Label="Forward" Click="MenuItem_Selected"
Visibility="{Binding IsHide}" Margin="30"/>
</StackPanel>
</SwapChainPanel>
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
private WinRTBridge.WinRTBridge _bridge;
private SplashScreen splash;
private Rect splashImageRect;
private WindowSizeChangedEventHandler onResizeHandler;
private Visibility _IsHide;
public Visibility IsHide
{
get { return _IsHide; }
set
{
_IsHide = value;
OnPropertyChanged("IsHide");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}......
private void MainPage_KeyDown(object sender, KeyRoutedEventArgs e)
{
Debug.WriteLine("Keydown");
if (!App.IsXbox())
e.Handled = true;
if (e.OriginalKey == Windows.System.VirtualKey.GamepadMenu)
{
Debug.WriteLine("GamepadView button clicked");
IsHide = Visibility.Collapsed;
}
}
Bindings without explicitly specified source object require that the target element's DataContext (or that of one of its parent elements) is set to an instance of the class the owns the binding source property.
So adding DataContext = this; to the constructor fixed the issue.

windows store apps How to bind visibility of an appbar item?

I have some problems with binding a visibility property of an appbar button.
I want to bind an appbar button visibility to another element visibility.
If the another element is visible - then the appbar is visible.
So here is my code:
<common:LayoutAwarePage.BottomAppBar>
<AppBar>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Visibility="{Binding ElementName=btnSave, Path=Visibility}"
Click="Edit_Click" />
...(more buttons)
</StackPanel>
</AppBar>
</common:LayoutAwarePage.BottomAppBar>
<Button Grid.Row="7" Grid.Column="0"
x:Name="btnSave"
Content="Save"
Style="{StaticResource EditModeButtonStyle}"
Click="Save_Click" />
I am changing the btnSave visibility in the code behind and no reaction in the appbar button's visibility. I have even tried to do the same binding with just a textblock, and it worked fine. I have also tried to use converter on the appbar (even thought I don't need) and I saw that the debugger was not reading the converter's methods. I saw some more people wrote similar appbar problems, but nothing of the answers is not helping me. Does someone know how can I do it? (I don't want to use code behind to change appbar visibility).
I suspect that appbar elements are not seeing the page's elements and hence element binding is not working. I would recommend you to use independent property which implements INotifyPropertyChanged interface. Bind that property to those elements for which you want to set the visibility.
C#
public sealed partial class BlankPage4 : Page, INotifyPropertyChanged
{
private Visibility _IsHide;
public Visibility IsHide
{
get { return _IsHide; }
set
{
_IsHide = value;
OnPropertyChanged("IsHide");
}
}
public BlankPage4()
{
this.InitializeComponent();
DataContext = this;
}
private void btnHideAll_Click(object sender, RoutedEventArgs e)
{
IsHide = Visibility.Collapsed;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
XAML
<Page.BottomAppBar>
<AppBar IsSticky="True" IsOpen="True">
<StackPanel Orientation="Horizontal">
<Button x:Name="btnHello" Visibility="{Binding IsHide}" Content="Hello" />
<TextBlock Visibility="{Binding IsHide}" Text="Hello" FontSize="20"/>
</StackPanel>
</AppBar>
</Page.BottomAppBar>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<Button x:Name="btnSave" Visibility="{Binding IsHide}" Content="Save" />
<Button Content="Hide All" Click="btnHideAll_Click" />
</StackPanel>
</Grid>

Categories