I set IsEnabled="False" for a Web Browser in Windows Phone 8, but it becomes gray instead of white.
Is there any way to prevent graying out for a web browser while setting IsEnabled to false?
Please don't tell me that it's a bad thing to do. The web browser must be disabled for a few moments, so a Pivot can grab swiping. My app is a hybrid PhoneGap + Native application, and each PivotItem contains a CordovaView element.
You may try to use UIElement.IsHitTestVisible property.
When you set its value to False it won't report any input events and cannot receive focus.
Instead of disabling directly, you could overlay a rectangle with a translucent white background. If placed in front of the web browser control it would handle interactions preventing the web browser from being edited and can be made visible by the same binding you currently use to control IsEnabled on the web browser.
If you want to be really helpful, you could use a border with a nested label to display a 'please wait' message to the user.
Just change it through the style, like so :
<phone:PhoneApplicationPage.Resources>
<Style x:Key="Chubs_WB" TargetType="phone:WebBrowser">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="phone:WebBrowser">
<Border x:Name="StateContainer" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Opacity="1">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WebBrowserStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<Storyboard>
<!--
<DoubleAnimation Duration="0" To=".4" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="StateContainer"/>
-->
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="PresentationContainer"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</phone:PhoneApplicationPage.Resources>
<phone:WebBrowser x:Name="myBrowser" Style="{StaticResource Chubs_WB}" />
We just get rid of the Double Animation on Disabled.
Related
I am trying to use visual states to mark a TextBox input as invalid (by changing its border color to red) during input validation when a user submits a form the TextBox is a part of. I have the following code:
XAML
<Page.Resources>
<!-- Other resources omitted for brevity -->
<Flyout x:Key="NewTimeBlockFlyout">
<StackPanel>
<!-- Other stuff here omitted for brevity -->
<TextBox Margin="5"
Header="Name"
x:Name="NewTimeBlockNameTextBox">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Default"></VisualState>
<VisualState x:Name="Invalid">
<VisualState.Setters>
<Setter Target="NewTimeBlockNameTextBox.Background" Value="Red"></Setter>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</TextBox>
<!-- The rest of the form omitted for brevity -->
<Button x:Name="CreateTimeBlockButton"
Grid.Column="0"
Margin="0,0,2,0"
HorizontalAlignment="Stretch"
Tapped="CreateTimeBlockButton_Tapped">Create</Button>
</StackPanel>
</Flyout>
</Page.Resources>
Note: This is on a XAML Page. I am NOT using a custom control.
C#
private void CreateTimeBlockButton_Tapped(object sender, TappedRoutedEventArgs e)
{
// Validate the input.
if (String.IsNullOrWhiteSpace(this.NewTimeBlockNameTextBox.Text))
{
// These two lines of code confirm the visual state named "Invalid" does exist on the textbox.
//List<VisualStateGroup> m = VisualStateManager.GetVisualStateGroups(this.NewTimeBlockNameTextBox).ToList();
//List<VisualState> c = m.FirstOrDefault().States.ToList();
// Assignment to bool just used to inspect the return value for debugging.
bool did = VisualStateManager.GoToState(this.NewTimeBlockNameTextBox, "Invalid", false);
}
}
Problem
No matter what I try, the call to VisualStateManager.GoToState() is always returning false.
Things I have tried:
Here is the relevant documentation from Microsoft.
As seen in the C# code above, I have verified the visual state "Invalid" does exist, as expected, on the "NewTimeBlockNameTextBox" control.
I have seen several solutions including here, and here that suggest moving the <VisualStateManager.VisualStateGroups> tag in the XAML to outside of the TextBox, or to the root of the Page. Neither have worked for me.
I have also seen these two solutions here and here, but neither seemed relevant to my situation, as both seem to have issues related to things I am not doing.
I can reproduce your issue. You need to place <VisualStateManager.VisualStateGroups> outside the TextBox and skip status through VisualStateManager.GoToState(this, "Invalid", false); Please refer to the following code.
Xaml code:
<Page
……
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Default"></VisualState>
<VisualState x:Name="Invalid">
<VisualState.Setters>
<Setter Target="NewTimeBlockNameTextBox.BorderBrush" Value="Red"></Setter>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBox Margin="5"
Header="Name"
x:Name="NewTimeBlockNameTextBox" >
</TextBox>
<Button x:Name="CreateTimeBlockButton"
Grid.Row="1"
Margin="0,0,2,0"
HorizontalAlignment="Stretch"
Tapped="CreateTimeBlockButton_Tapped">Create</Button>
</StackPanel>
</Page>
Code behind:
private void CreateTimeBlockButton_Tapped(object sender, TappedRoutedEventArgs e)
{
bool a = VisualStateManager.GoToState(this, "Invalid", false);
}
Updated:
For using VisualStateManager.GoToState(), which always be done by changing its controltemplate.
You could right click the textbox in XAML designer, then select the option Edit a Template->Edit a Copy, here you will see the default textbox style placed in <Page.Resources> </Page.Resources> tag.
<Style x:Key="TextBoxStyle1" TargetType="TextBox">
……
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
……
<VisualStateManager.VisualStateGroups>
……
<VisualState x:Name="TestState">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="red"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="HeaderContentPresenter" …/>
<Border x:Name="BorderElement" …/>
……
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see, you could place custom state in its template, then you could use “VisualStateManager.GoToState(NewTimeBlockNameTextBox, "TestState", false);” to skip state.
I'm just starting to learn UWP and xaml. What is the proper way to add a AutoSuggestBox to the Side Navigation panel? (Sorry for the bad code formatting in advance, copy and paste wasn't great)
My Main.xaml has an AutoSuggestArea that I have set to Visible
</VisualStateGroup>
<VisualStateGroup x:Name="AutoSuggestGroup">
<VisualState x:Name="AutoSuggestBoxVisible"/>
<VisualState x:Name="AutoSuggestBoxCollapsed">
<VisualState.Setters>
<Setter Target="AutoSuggestArea.Visibility" Value="Visible"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
and in the Grid for the AutoSuggestArea I have defined an AutoSuggestBox
<Grid x:Name="AutoSuggestArea" Height="44" Grid.Row="3" VerticalAlignment="Center">
<ContentControl x:Name="PaneAutoSuggestBoxPresenter" Content="{TemplateBinding AutoSuggestBox}" HorizontalContentAlignment="Stretch" IsTabStop="False" Margin="16,0,16,0" VerticalContentAlignment="Center"/>
<Button x:Name="PaneAutoSuggestButton" Content="" MinHeight="44" Style="{TemplateBinding PaneToggleButtonStyle}" Visibility="Collapsed" Width="{TemplateBinding CompactPaneLength}"/>
<AutoSuggestBox Width="234" VerticalAlignment="Center"
HorizontalAlignment="Center"
PlaceholderText="Search" Name ="boxS"
QuerySubmitted="AutoSuggestBox_QuerySubmitted"
TextChanged="AutoSuggestBox_TextChanged">
<AutoSuggestBox.TextBoxStyle>
<Style TargetType="TextBox">
<Setter Property="IsHandwritingViewEnabled" Value="False"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
</AutoSuggestBox.TextBoxStyle>
<AutoSuggestBox.QueryIcon>
<SymbolIcon Symbol="Find" Foreground="Black">
<SymbolIcon.RenderTransform>
<CompositeTransform ScaleX="1" ScaleY="1"/>
</SymbolIcon.RenderTransform>
</SymbolIcon>
</AutoSuggestBox.QueryIcon>
</AutoSuggestBox>
</Grid>
What I want is basically Identical Behaviour as the Groove Music app on Windows, where the Search bar disappears as the Nav View is closed or Minimized.
Instead I get this
I am assuming you meant NavigationView by NavigationPanel.
This is not how you put an AutoSuggestBox in NavigationView. NavigationView has an NavigationView.AutoSuggestBox property. You just set an AutoSuggestBox on this property, and every thing will work as expected. Like this:
<NavigationView>
<NavigationView.AutoSuggestBox>
<AutoSuggestBox x:Name="NavViewSearchBox" QueryIcon="Find"/>
</NavigationView.AutoSuggestBox>
</NavigationVew>
You don't have to hide/show this AutoSuggestBox yourself. NavigationView will automatically do this for you. Also, you don't have to put thie AutoSuggestBox inside any grid or anything.
I'm having a really hard time finding a way to do the following...
I have my "Image button style," and it is applied to every button in my Silverlight app. Is there any way to make a blanket VisualStateManager to change the image on MouseOver, that will work for every button? I have a couple ideas, but I'm not sure if they can be implemented...
Let's say my button image paths are consistent:
image1.png
image2.png
and
image1 - hover.png
image2 - hover.png
Is there a way to change the path of the image to append " - hover"? I thought about using an IValueConverter for this, but wasn't sure how to access the control state...
An alternative idea I had was if there was a way to accomplish this:
<Button>
<Image Source="../Images/image1.png" Width="70"/>
<Image Source="../Images/image1 - hover.png" Width="70"/>
</Button>
Have two contents (an array of content?) and on Normal state, set only the first content opacity to 1, and the rest to 0. Then on MouseOver, switch the opacities.
Are any of these solutions feasible, and how can they be implemented?
Thanks
Edit: I know I can make custom styles for each button that switch out their images, but I would like a blanket style that I can apply to all buttons.
You may (ab)use the Tag property for your purpose and create a ControlTemplate with two Image controls with a BitmapImage that binds its UriSource property to either the Content or the Tag property respectively:
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal"/>
<VisualState Name="MouseOver">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="image1"
Storyboard.TargetProperty="Opacity"
To="0" Duration="0:0:0.1"/>
<DoubleAnimation
Storyboard.TargetName="image2"
Storyboard.TargetProperty="Opacity"
To="1" Duration="0:0:0.1"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Image x:Name="image1">
<Image.Source>
<BitmapImage UriSource="{Binding Content,
RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</Image.Source>
</Image>
<Image x:Name="image2" Opacity="0">
<Image.Source>
<BitmapImage UriSource="{Binding Tag,
RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</Image.Source>
</Image>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now you may declare a Button like this:
<Button Content="../Images/image1.png" Tag="../Images/image1_hover.png"/>
I'm developing a xaml/c# metro style app in windows 8. I'd like to emulate the Microsoft Calendar app comboBox Style (In the event details page). I mean, having that behavior of coloured box and border after selection. How can I do it using visual states?
There is no standard control for this, you have to create your own / extend the standard combobox
Something like this should work:
<Combobox.Template>
<ControlTemplate>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Unfocused"/> <!--leave the unfocused state empty if the control already looks "unfocused" -->
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="background" Storyboard.TargetProperty="Opacity" To="0.2" Duration="0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="background" Background="Red" Opacity="0" />
<!--other stuff-->
</ControlTemplate>
</Combobox.Template>
The Combobox control automatically switches it's built-in states according to mouse/keyboard input like focused, pressed, mouse over etc. By switching a state the storyboard that was defined for the current state will be reversed and the storyboard that you have defined for the new state will be applied. You can review the available states here: http://msdn.microsoft.com/en-us/library/ms752094.aspx
(Using code-behind you can also implement your own states based on events and such, but this should be rarely needed.)
I'm wondering if I can have a individual component in a control have an event. For example, I've created my own control, and with VisualStateManager I'm able to handle several events that fire for the control as a whole, I'd like just my togglebutton in the controlto fire the mouseover event. Currently any area of the control that the mouse is over fires the mouseover which ruins the coloranimation effect i'm trying to get, I want the coloranimation to only happen when the toggle button has a mouse over, my control has a contentpresent allowing for other content, i don't want that piece to fire the event.
Example of what i'm talking about below in generic.xaml file.
<Style TargetType="local:MyControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyControl">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ViewStates">
<VisualState x:Name="Expanded">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ContentScaleTransform" Storyboard.TargetProperty="ScaleY" To="1" Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Collapsed">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ContentScaleTransform" Storyboard.TargetProperty="ScaleY" To="0" Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<!-- This fires for any part of the control, is it possible to just create a mouseover for the ToggleButton below? -->
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" Background="{TemplateBinding Background}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Margin="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ToggleButton Grid.Column="0" Content="{TemplateBinding HeaderContent}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RenderTransformOrigin="0.5,0.5" Margin="1" x:Name="ExpandCollapseButton">
</ToggleButton>
</Grid>
<ContentPresenter Grid.Row="1" Margin="5" Content="{TemplateBinding Content}" x:Name="Content">
<ContentPresenter.RenderTransform>
<ScaleTransform x:Name="ContentScaleTransform"/>
</ContentPresenter.RenderTransform>
</ContentPresenter>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Bob, You can access the togglebutton from your class like this:
ToggleButton myToggleButton = GetTemplateChild("toggleButton") as ToggleButton;
Create the events you want in your class. You may need to override the OnApplyTemplate method and create your event there, I'm still researching this part and don't fully understand it yet, you will have to play with it. I did override my OnApplyTemplate and it worked for me.
ToggleButton myToggleButton;
public override void OnApplyTemplate() {
base.OnApplyTemplate();
myToggleButton = GetTemplateChild("toggleButton") as ToggleButton;
myToggleButton.MouseEnter += new MouseEventHandler(myToggleButton_MouseEnter);
}
void myToggleButton_MouseEnter(object sender, MouseEventArgs e) {
VisualStateManager.GoToState(this, "MouseEnter", true);
}
Also make sure to setup your Template at the top:
[TemplateVisualState(Name = "MouseEnter", GroupName = "ViewStates")]
The VisualState can exist in the generic.xaml file where you are setting up your other visualstates and does not need to be in the inner ToggleButton.
<VisualState x:Name="MouseEnter">
<Storyboard>
<ColorAnimation Storyboard.TargetName="toggleButton" Storyboard.TargetProperty="(ToggleButton.SomeProperty).(SolidColorBrush.Color)" To="SomeColor"/>
</Storyboard>
</VisualState>
First of all lets get our terminology correct, you are not talking about "events" you are talking about "visual states". The "MouseOver" is a visual state. Its the responsibility of code within the control to decide which of the visual states the control is in.
Ordinarily code in the control will use the MouseEnter and MouseLeave events to set a boolean to indicate that the mouse is over the control and then call some UpdateStates method in which the developer will include logic to determine which visual states the control ought to be in currently.
In your case rather than using the controls MouseEnter and MouseLeave events attach these handlers to your inner ToggleButton instead.