not able to disable a particular text block in custom control - c#

I have a custom control which contains one text-block, one combo-box and one hyper-link button.
<UserControl x:Class="IXExpress.Controls.WorkspaceIndexes"
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:telerikSdk="http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable="d"
Height="Auto" Width="Auto">
<Grid x:Name="LayoutRoot">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<TextBlock x:Name="IndexNameTextBlock" Text="{Binding ApplicationStrings.SelectIndexName, Source={StaticResource ResourceWrapper}, Mode=OneTime}" Margin="3,5" TextAlignment="Left" VerticalAlignment="Center" Visibility="Visible"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<telerikSdk:RadComboBox x:Name="IndexNameCB"
DisplayMemberPath="IndexName"
HorizontalAlignment="Center"
IsDropDownOpen="False"
Margin="3,0,3,5"
MinWidth="150"
Width="150"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Visibility="Visible"
SelectionChanged="IndexNameCB_SelectionChanged"/>
<HyperlinkButton x:Name="CreateNewIndexLink"
Content="Create New"
VerticalContentAlignment="Center"
Click="CreateNewIndexLink_Click"/>
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
I am using it on another page as following:
<StackPanel Orientation="Vertical">
<customControls:WorkspaceIndexes x:Name="WorkspaceIndexes" IsMoreTextRequired="True" Margin="3"/>
</StackPanel>
The issue is, on some condition when I want to disable this control but it only disables combo-box and hyper-link button.
code:
if (my condition)
WorkspaceIndexes.IsEnabled = true;
else
WorkspaceIndexes.IsEnabled = false;
Result:
http://imgur.com/L6tbOwo
I also don't see IsEnabled option for "IndexNameTextBlock" text-block, Why is that?

You can't see the IsEnabled property for the TextBlock because it doesn't have the property. The other Elements are derived from Control, they can be enabled and disabled. The TextBlock is no Control. Disabling a TextBlock would be meaningless. It just displays text. No user interaction possible.
If you need it to be grayed out you have to change either its Foreground color, or reduce its Opacity, or place a semi-transparent Rectangle/Border over it.

Related

How `TextControlPlaceholderForeground` resource doesn't appy to TextBox

I got started learning Universal Windows Apps. For my demo application, I am trying to change the placeholder foreground of a TextBox control. To set its color, I set a resource key called TextControlPlaceholderForeground (as per this documentation) on the same XAML page definition that contains the control. However, the placeholder color of TextBox is not set. It looks as if no placeholder text is set when the control is not in a focused state. When it receives focus, the placeholder becomes visible, but still not the color that is set to it. Here is my XAML:
<Page
x:Class="MyApp.AuthenticationPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<SolidColorBrush x:Key="TextControlPlaceholderForeground" Color="Green" />
</Page.Resources>
<Grid>
<Border
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Margin="0,0,0,10"
Background="White"
Padding="10"
CornerRadius="10"
Width="300"
>
<StackPanel Orientation="Vertical">
<!-- The placeholder of the TextBox below doesn't become green -->
<TextBox x:Name="emailInput" PlaceholderText="Email" Margin="0,0,0,10" />
<!-- However, the placeholder of this PasswordBox becomes green -->
<PasswordBox x:Name="passwordInput" PlaceholderText="Password" Margin="0,0,0,10" />
<Button HorizontalAlignment="Stretch" Content="LOG IN" Click="onLoginSubmit" Style="{StaticResource AccentButtonStyle}"/>
<HyperlinkButton FontSize="11" Foreground="Black" Content="Forgot your password?" HorizontalAlignment="Center" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Text="Don't have an account yet?" Foreground="Black" FontSize="11" Padding="0,0,5,0"/>
<HyperlinkButton Padding="0" FontWeight="Normal" >
<TextBlock Text="Create new account" Foreground="Black" TextDecorations="Underline" FontSize="11"/>
</HyperlinkButton>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Page>
An observation: When I try to set TextBox's placeholder text color via Style tags, it works.
<Style x:Key="TextBoxStyle" TargetType="TextBox">
<Setter Property="PlaceholderForeground" Value="Green" />
</Style>
I didn't understand what happens here. I know I am missing something very small but couldn't see it.
First, let me explain why the second approach works. There is a little bit of difference between the PasswordBox and the TextBox about how they defined the Placeholder Text color. Both of the PasswordBox and the TextBox has a PlaceholderTextContentPresenter element in their styles which is a TextBlock. But they have different value for the Foreground property when using this TextBlock.
TextBox:
<TextBlock x:Name="PlaceholderTextContentPresenter" Foreground="{Binding PlaceholderForeground, RelativeSource={RelativeSource Mode=TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForeground}}"
PasswordBox
<TextBlock x:Name="PlaceholderTextContentPresenter" Foreground="{ThemeResource TextControlPlaceholderForeground}"
You could see that the PasswordBox is directly using the TextControlPlaceholderForeground that you defined as the color but the TextBox is using a binding and the binding source is the PlaceholderForeground property. So when you set this property, the TextBox will show the color as you want.
So back to the first question, if you want to change the foreground of the Placeholder Text, you will need to create a default style of the TextBox and change the binding of the Foreground of the PlaceholderTextContentPresenter element to use the TextControlPlaceholderForegrounddirectly like what the **PasswordBox ** did.

Dock one panel between two others

I have three panels:
The first one is on the top, it holds some buttons only. It will be as high as many buttons will be there.
The second ones should be directly under it, it holds a canvas that should take up most of the window.
The third one is "some kind of" status bar, it will hold some labels and data. It will be also only as high as many labels are added there.
I don't want to hardcode any sizes. So I am docking the first panel to the Top of the parent. The same goes for the 2nd panel (canvas). I am docking it also to the top. The third panel is docked to the bottom.
I can't make the canvas(2nd panel) fill the whole space between 1st panel and 3rd panel. How to do it?
<Window x:Class="MyProject.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:MyProject"
mc:Ignorable="d"
Title="MainWindow" Height="700" Width="800">
<DockPanel LastChildFill="False">
<StackPanel DockPanel.Dock="Top">
<GroupBox x:Name="grBoxSettings" Header="Settings" HorizontalAlignment="Stretch" VerticalAlignment="Top" Height="90" Margin="5,0,5,0">
<WrapPanel x:Name="wrapPanelButtons" HorizontalAlignment="Left" VerticalAlignment="Top" Width="110">
<Button x:Name="btnTest" Content="Test" Margin="5,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" Width="100"/>
</WrapPanel>
</GroupBox>
</StackPanel>
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch" DockPanel.Dock="Top"/>
<DockPanel LastChildFill="False" DockPanel.Dock="Bottom">
<GroupBox Header="Version" DockPanel.Dock="Right">
<Label x:Name="lblVersion"/>
</GroupBox>
</DockPanel>
</DockPanel>
</Window>
Either use a Grid with three RowDefinitions with Height= 1st: Auto 2nd: 1* 3rd: Auto,
Or Simply switch around the order in your DockPanel:
<DockPanel LastChildFill="True">
<StackPanel DockPanel.Dock="Top">
<GroupBox x:Name="grBoxSettings" Header="Settings" HorizontalAlignment="Stretch" VerticalAlignment="Top" Height="90" Margin="5,0,5,0">
<WrapPanel x:Name="wrapPanelButtons" HorizontalAlignment="Left" VerticalAlignment="Top" Width="110">
<Button x:Name="btnTest" Content="Test" Margin="5,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" Width="100"/>
</WrapPanel>
</GroupBox>
</StackPanel>
<DockPanel LastChildFill="False" DockPanel.Dock="Bottom">
<GroupBox Header="Version" DockPanel.Dock="Right">
<Label x:Name="lblVersion"/>
</GroupBox>
</DockPanel>
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</DockPanel>
Also, here's some documentation for the Dock Property:
If you set the LastChildFill property to true, which is the default setting, the last child element of a DockPanel always fills the remaining space, regardless of any other dock value that you set on the last child element. To dock a child in another direction, you must set the LastChildFill property to false and must also set an explicit dock direction on the last child element.

Binding visibility of usercontrol does not collapse control

i do have a problem with binding the visibility of my usercontrol.
The binding to a Dependency Property of type Visibility works fine and the correct value (in this case Collapsed) is held by the DP. The content of my Grid within the UserControl is set to collapsed, but the hole control doesnt collapse. It still keeps the space occupied defined by with and heigth, as referenced in the xaml.
EDIT: i found out, that the problem is that i set width and height in the xaml where i reference my usercontrol. if i don't do this, the control collapses correct (therefore binding works fine). But i need to set width and heigth in case the usercontrol is visible.
Any idea how i can solve this problem?
<my:MenuButtonBase x:Class="bxSuite.Controls.MenuButtonLarge"
xmlns:my="clr-namespace:bxSuite.Controls"
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"
Background="Black"
>
<Grid Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=ButtonVisibility}" >
<StackPanel>
<Image Source="{Binding ButtonImageSource}" Margin="5,10,5,5" Width="48" Height="48" VerticalAlignment="Top" HorizontalAlignment="Center" />
<TextBlock Text="{Binding FunctionHeader}" Foreground="White" TextWrapping="Wrap" TextAlignment="Center" Padding="5,5,5,5" FontSize="12" />
</StackPanel>
</Grid>
</my:MenuButtonBase>
In XAML i reference my usercontrol like this (where the Converter produces the visibility-state correctly):
<my:MenuButtonLarge Name="btnInEuqipment" ButtonVisibility="{Binding Path=User, Converter={StaticResource ConverterUserRightVisibility}, ConverterParameter=5}" VerticalAlignment="Top" FunctionHeader="{lex:Loc Key=MenuButton_InEquipment}" Width="130" ButtonImageSource="/bxSuite.RolloutManager;component/Images/inequipment_48x48.png" BackgroundEnabled="#FF0694FD" BackgroundHover="#FF0072C6" MenuButtonClick="btnInEuqipment_MenuButtonClick" Height="95" Margin="5,10,0,0" />
Try set the visibility of the user control instead of the grid, should work.
Your code should be like this.
<my:MenuButtonBase x:Class="bxSuite.Controls.MenuButtonLarge"
xmlns:my="clr-namespace:bxSuite.Controls"
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"
Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=ButtonVisibility}"
Background="Black">
<Grid>
<StackPanel>
<Image Source="{Binding ButtonImageSource}"
Margin="5,10,5,5"
Width="48"
Height="48"
VerticalAlignment="Top"
HorizontalAlignment="Center" />
<TextBlock Text="{Binding FunctionHeader}"
Foreground="White"
TextWrapping="Wrap"
TextAlignment="Center"
Padding="5,5,5,5"
FontSize="12" />
</StackPanel>
</Grid>
Dont forget to update the RelativeSource of your bind.

Setting VirtualizingStackPanel.IsVirtualizing in a Windows 8.1 Store App

I have a XAML page in a Windows 8.1 Store App. I set the data context for a ListView but I initially have it collapsed. What I am trying to do is toggle the visibility of some of the elements in the ListView before making it visible. But it doesn't load them unless it becomes visible. So, to forced it to load the items, I am trying to set "IsVirtualizing" to false so that I don't have to worry about it (and I don't mind the hit in performance since I won't have that many items). But for all the examples I look at, all I get is
The property "IsVirtualizing" does not have an accessible setter.
Not sure what is going on here.
Here is the relevant piece of code with the other contents stripped out.
<common:LayoutAwarePage
x:Class="FlashMe.DeckView"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:FlashMe"
xmlns:common="using:FlashMe.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
>
<ScrollViewer x:Name="deckScrollViewer" Grid.Row="1" VerticalScrollMode="Disabled" HorizontalScrollMode="Enabled" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled" Margin="0,15,0,0">
<StackPanel x:Name="deckStackPanel" Orientation="Horizontal">
<Grid Width="100" x:Name="MarginBuffer" />
<ListView x:Name="cardsListViewDisplay" Visibility="Collapsed" SelectionMode="None" Width="500" ItemsSource="{Binding Path=FlashCardsAsList}" VirtualizingStackPanel.IsVirtualizing="False">
<ListView.ItemTemplate>
<DataTemplate>
<Border>
<StackPanel Orientation="Vertical" Width="490" Height="400" RightTapped="FlashCardRightClicked">
<Grid Width="490" Height="200" Background="Gainsboro">
<TextBlock Text="{Binding Path=Front}"
Foreground="Black"
Style="{StaticResource GroupHeaderTextStyle}"
Margin="4,0,4,4"
FontWeight="SemiBold"
VerticalAlignment="Center"
HorizontalAlignment="Center"
TextWrapping="Wrap"
MaxWidth="410"/>
</Grid>
<Grid Width="500" Height="200" Background="{Binding ElementName=deckStackPanel, Path=DataContext.DeckColorBrush}">
<TextBlock Text="{Binding Path=Back}"
Foreground="White"
Style="{StaticResource GroupHeaderTextStyle}"
Margin="4,0,0,4"
FontWeight="SemiBold"
VerticalAlignment="Center"
HorizontalAlignment="Center"
TextWrapping="Wrap"
MaxWidth="410"/>
</Grid>
</StackPanel>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</ScrollViewer>
</common:LayoutAwarePage>
In Windows Store Apps, the IsVirtualizing property is read-only.
From the Remarks section on the VirtualizingStackPanel.IsVirtualizingProperty page on MSDN:
VirtualizingStackPanel.IsVirtualizing is an atypical attached property
because it does not have a Set accessor, and thus is not really a XAML
attached property with a markup usage. Instead,
VirtualizingStackPanel.IsVirtualizing functions as a sentinel whereby
child elements can query the VirtualizingStackPanel parent, and
determine whether virtualization is being used. ...

How to add controls dynamically to a UserControl through user's XAML?

I want to create a user control that contains a TextBlock and a StackPanel that will allow the user to add his/her own controls to the user control dynamically in XAML.
Here is the sample XAML for my UserControl:
<UserControl x:Class="A1UserControlLibrary.UserControlStackPanel"
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"
mc:Ignorable="d"
d:DesignHeight="200" d:DesignWidth="300">
<StackPanel>
<TextBlock Text="I want the user to be able to add any number of controls to the StackPanel below this TextBlock."
FontFamily="Arial" FontSize="12" FontWeight="DemiBold" Margin="5,10,5,10" TextWrapping="Wrap"/>
<StackPanel>
<!-- I want the user to be able to add any number of controls here -->
</StackPanel>
</StackPanel>
</UserControl>
I would like the user to be able to embed this user control in their XAML and add their own controls to the stack panel of the user control:
<uc:A1UserControl_StackPanel x:Name="MyUserControl_Test" Margin="10" Height="100">
<Button Name="MyButton1" Content="Click" Height="30" Width="50"/>
<Button Name="MyButton2" Content="Click" Height="30" Width="50"/>
<Button Name="MyButton3" Content="Click" Height="30" Width="50"/>
</uc:A1UserControl_StackPanel>
Doing this using the above XAML does not work. Any ideas?
You can do that, although not quite like your example. You need two things. The first is to declare a DependencyProperty of type UIElement, of which all controls extend:
public static DependencyProperty InnerContentProperty = DependencyProperty.Register("InnerContent", typeof(UIElement), typeof(YourControl));
public UIElement InnerContent
{
get { return (UIElement)GetValue(InnerContentProperty); }
set { SetValue(InnerContentProperty, value); }
}
The second is to declare a ContentControl in the XAML where you want the content to appear:
<StackPanel>
<TextBlock Text="I want the user to be able to add any number of controls to the StackPanel below this TextBlock."
FontFamily="Arial" FontSize="12" FontWeight="DemiBold" Margin="5,10,5,10" TextWrapping="Wrap"/>
<StackPanel>
<ContentControl Content="{Binding InnerContent, RelativeSource={RelativeSource AncestorType={x:Type YourXmlNamspacePrefix:ContentView}}}" />
</StackPanel>
</StackPanel>
In my opinion, if you use StackPanels, you could find that your content does not get displayed correctly... I'd advise you to use Grids for layout purposes for all but the simplest layout tasks.
Now the one difference to your example is in how you would use your control. The InnerContent property is of type UIElement, which means that it can hold one UIElement. This means that you need to use a container element to display more than one item, but it has the same end result:
<YourXmlNamspacePrefix:YourControl>
<YourXmlNamspacePrefix:YourControl.InnerContent>
<StackPanel x:Name="MyUserControl_Test" Margin="10" Height="100">
<Button Content="Click" Height="30" Width="50"/>
<Button Content="Click" Height="30" Width="50"/>
<Button Content="Click" Height="30" Width="50"/>
</StackPanel>
</YourXmlNamspacePrefix:YourControl.InnerContent>
</YourXmlNamspacePrefix:YourControl>
And the result:
UPDATE >>>
For the record, I know exactly what you want to do. You, it seems, do not understand what I am saying, so I'll try to explain it one last time for you. Add a Button with the Tag property set as I've already shown you:
<Button Tag="MyButton1" Content="Click" Click="ButtonClick" />
Now add a Click handler:
private void ButtonClick(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
if (button.Tag = "MyButton1") DoSomething();
}
That's all there is to it.

Categories