set visibility of multiple elements in XAML by one variable - wpf

when working on the design, i want to be a able to control visibility of multiple components i want to be able to control all of the isHidden from a single property.
so far my code looks like this
ignoreable="e d"
<StackPanel d:IsHidden=true>
...
</StackPanel>
<StackPanel e:IsHidden=false>
...
</StackPanel>
<StackPanel d:IsHidden=true>
...
</StackPanel>
<StackPanel e:IsHidden=false>
...
</StackPanel>
is there any way to control the visibility of all of the panels from a single variable?
so it will look like this
<StackPanel d:IsHidden=isVisibleVar>
...
</StackPanel>
<StackPanel e:IsHidden=isVisibleVarOther>
...
</StackPanel>
i'm aware of converters. i know how to do this at runtime, what i want to is have a fast way to switch between visibility of the two groups from one place, instead of search & replace

found a work around.
use a style for each group. then i only need to set the visibility in two locations.
<Style x:Key="MainButtonStyle"
TargetType="Button"
BasedOn= "{StaticResource BasicButton}">
<Setter Property="Visibility" Value="Visible"></Setter>
</Style>
<Style x:Key="SecButtonStyle"
TargetType="Button"
BasedOn= "{StaticResource BasicButton}">
<Setter Property="Visibility" Value="Hidden"></Setter>
</Style>

My answer may not be such a high sophisticated one and did not use only a "single variable", but it will do the trick (using two variables).
So at first you define two variables in your XAML. For example directly in the Window.Resources like:
<Window ...
xmlns:system="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
>
<Window.Resources>
<system:Boolean x:Key="ShowInDemoMode">False</system:Boolean>
<system:Boolean x:Key="HideInDemoMode">True</system:Boolean>
</Window.Resources>
...
</Window>
or - if you have one - in your Style-ResourceDictionary
<ResourceDictionary ...
xmlns:system="clr-namespace:System;assembly=mscorlib"
>
<system:Boolean x:Key="ShowInDemoMode">False</system:Boolean>
<system:Boolean x:Key="HideInDemoMode">True</system:Boolean>
...
</ResourceDictionary>
Then you can use the two like this:
<StackPanel d:IsHidden="{StaticResource HideInDemoMode}">
...
</StackPanel>
<StackPanel d:IsHidden="{StaticResource ShowInDemoMode}">
...
</StackPanel>
<StackPanel d:IsHidden="{StaticResource HideInDemoMode}">
...
</StackPanel>
<StackPanel d:IsHidden="{StaticResource ShowInDemoMode}">
...
</StackPanel>
With this static resources you can easily switch between the visibility of your StackPanel items by changing the values of these two resources.
Remark:
Setting d:IsHidden to true or false is only active in DesignTime and will show the items when running your application, which is a major difference to your answer.

Related

How To Make A WPF UserControl Act As A Container

I'm trying to create a Toolbar control that can group selected buttons with a border and a label. If there is already a built-in control that will do this then I could use that instead of building a UserControl.
If not, then what I'm wanting to build is a UserControl that would allow me to enter one-to-many of my ImageButton UserControls and set a GroupLabel text like below. Can this be done in WPF?
<User_Controls:ToolbarGroup GroupLabel="Entity">
<User_Controls:ImageButton ButtonText="Entity Setup"/>
<User_Controls:ImageButton ButtonText="New Entity"/>
</User_Controls:ToolbarGroup>
PS: I would post an image but this quirky forum won't allow me to post an image.
If i have got you correctly then I think you can achieve this way also, and on mouse eneter and leave event you can do the button click job.
for setting text you can use a grid and a label inside it to set the text, and Image buttons below it.
<UserControl x:Class="ABC.View.Oats"
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="300" d:DesignWidth="300">
<Grid>
<Image Source="{Binding Image}" Stretch="Fill"/>
</Grid>
</UserControl>
I think what you're looking for is a GroupBox, it has a header property where you can set the label.
Something like this:
<GroupBox Width="300" Height="100">
<GroupBox.Header>
<Label>Text</Label>
</GroupBox.Header>
<StackPanel>
<Button Content="Button"/>
<Button Content="Button"/>
<Button Content="Button"/>
</StackPanel>
</GroupBox>
I would also recommend using the groupbox, it seems to be doing exactly what you want it to do and it looks neat. Here's some examples on how to use them: http://www.dotnetperls.com/groupbox-wpf
On the other hand, if you believe the groupbox is not sufficient, you could create a control that inherits from the groupbox and you could extend it and add whatever you need to it. It would look like this:
public class customGroupBox: GroupBox{
....Add whatever you need here
}
Thanks for the replies. I tried the GroupBox and it's not the layout we want because we want the label underneath the buttons and centered. I never could find a way to add a collection to the UserControl. Maybe I didn't ask the question right by calling it a container. The code below will work, but it's not elegant. I wanted something that would wrap the layout in a UserControl and allow me to add a variable number of buttons to each toolbar group.
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0">
<Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<User_Controls:ImageButton ButtonText="New 1"/>
<User_Controls:ImageButton ButtonText="New 2"/>
<User_Controls:ImageButton ButtonText="New 3"/>
</StackPanel>
<Label HorizontalAlignment="Center" Content="Group 1"/>
</StackPanel>
</Border>
<Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<User_Controls:ImageButton ButtonText="New 4"/>
</StackPanel>
<Label HorizontalAlignment="Center" Content="Group 2"/>
</StackPanel>
</Border>
</StackPanel>
One way to accomplish this is with a custom styled ItemsControl.
You can then reuse it and just bind it to different data.
Please forgive me, this is hand-typed...
In your resources...
<Style x:Key="ToolbarGroupItemsControlStyle" TargetType="ItemsControl">
...
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ItemsControl">
<Grid>
... XAML to form your group with a binding to the
... group name
<ItemsPresenter/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="ToolbarGroupItemTemplate">
<Grid>
... XAML and binding for each toolbar group item ...
</Grid>
</DataTemplate>
In your XAML...
<ItemsControl
Style="{DynamicResource ToolbarGroupItemsControlStyle}"
ItemsSource="{Binding ToolbarGroupItems}"
ItemTemplate="{DynamicResource ToolbarGroupItemTemplate"/>
If your resources above are at the application level, then you can place the ItemsControl above on any Window/UserControl you want.
Your ItemsSource will need to be a collection of a custom type you create that has bindings for the button text, etc.
I hope this is helpful.

DevExpress NavBarItem won't data bind properly in ContentTemplate that uses a WPF TreeView

I'm trying to organize my NavBarItem elements in each NavBarGroup into a tree view, using the following code:
<dxn:NavBarControl DataContext="{Binding}" ItemsSource="{Binding Bars}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<dxn:NavBarControl.Resources>
<Style TargetType="dxn:NavBarGroup">
<Setter Property="Header" Value="{Binding DisplayText}"/>
<Setter Property="Content" Value="{Binding MenuItems}"/>
<Setter Property="DisplaySource" Value="Content"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TreeView x:Name="MenuView" ItemsSource="{Binding}" >
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=ChildItems}" >
<ContentControl>
<dxn:NavBarItem
DataContext="{Binding}"
Content="{Binding ItemText}" PreviewMouseUp="MenuItemOnPreviewMouseUp" Initialized="FrameworkContentElement_OnInitialized" />
</ContentControl>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</dxn:NavBarControl.Resources>
<dxn:NavBarControl.View>
<dxn:ExplorerBarView/>
</dxn:NavBarControl.View>
</dxn:NavBarControl>
The groups are binding correctly, and I am only populating one group, "Personnel" for debugging reasons, with the mini-hierarchy:
"Personnel"
--"Employees"
----"Contractors"
------"Time-sheets"
I get the correct structure in the treeview, but each item only has the text that would result from calling NavBarItem.ToString(). When I handle the NavBarItem.Initialized even, the sender argument, being a NavBarItem actually has the correct value in its Content property, so the binding isn't all broken, but I don't know what is, and am seeking help here.
First of all it is necessary to notice that NavBarGroup and NavBarItem are non-visual elements. Thus if you use them as the ContentPresenter content only simple strings will be shown (just like you see in your case).
The second thing is that multi-level hierarchy is not supported in NavBar (only group level and item level).
So if you need to show more than two levels you can use TreeView as you used in your sample but put TreeViewItems to the content template instead of putting NavBarItems; If you need only two levels you can use NavBarControl.ItemsSource and NavBarGroup.ItemsSource properties to populate layout.

How to customize default context menu

In my WPF application I want to make my all textboxes cut, copy and paste restricted.
One way to do this is set ContextMenu ="{x:Null}"
But by doing this I will loose the spell check suggestions which I don't want to loose. Also In my application I have 1000 textboxes so I want to do this is in a more optimize way.
Any advice will be appreciated.
If all you need is menu items related to spell checking, you can refer to this MSDN article:
How to: Use Spell Checking with a Context Menu.
If you want to apply custom ContextMenu to multiple (but not all) textboxes:
<Window.Resources>
<ContextMenu x:Key="MyCustomContextMenu">
<MenuItem Header="Ignore All" Command="EditingCommands.IgnoreSpellingError" />
</ContextMenu>
</Window.Resources>
<Grid>
<TextBox Height="23" Name="textBox1" Width="120" SpellCheck.IsEnabled="True"
ContextMenu="{StaticResource MyCustomContextMenu}" />
</Grid>
If you want to apply custom ContextMenu to ALL textboxes:
<Window.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem
Header="Ignore All"
Command="EditingCommands.IgnoreSpellingError" />
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TextBox Height="23" Name="textBox1" Width="120" SpellCheck.IsEnabled="True" />
</Grid>
NOTE:
You can move the context menu resource to application level instead of the window level.
The MSDN article mentions to get menu items via C# code and not via XAML. I could easily port the "Ignore All" command to XAML (code snippets above), but for spelling suggestions, you will have to do some R&D.

Master page but for Regions?

I have a RibbonBar with four buttons, each of which selects a different view and injects it into the MainRegion. Right now, it's working well but each of the four views have a few controls in common e.g. Displaying the username, date/time, search box etc. As of now, I've made separate views but I would like to know if there is a way of implementing a Master Page/UserControl so that I don't have to repeat code.
So the design, right now, is like so:
Shell
<Window>
<Grid>
<DockPanel>
<RibbonBar Regions:RegionManager.RegionName="ToolbarRegion">
</RibbonBar>
<ContentControl Regions:RegionManager.RegionName="MainRegion">
</ContentControl>
</DockPanel>
</Grid>
</Window>
The ToolbarRegion contains the RibbonBar with the four buttons.
Each Button will inject a view into the MainRegion. Each of these views has some common controls (much like a Master Page in ASP.Net), but the content of each view is different.
There are ways to work around this (I can't change the Shell design) but I was wondering if there was a better, more elegant way to do this.
I like using the Prism framework, however I feel that their Regions should only be used for Application Layout (MenuRegion, NavigationRegion, ContentRegion, etc), and not Navigation. Using them for Navigation means letting the View control the application flow, and I feel that is a job for the ViewModels.
My preferred method for displaying changing content is with DataTemplates and ContentControls
To create something like you outlined, I would have a parent ViewModel which contains
ObservableCollection<IPageViewModel> PageViewModels
IPageViewModel SelectedPageViewModel
The area I wanted to display the dynamic content would use a ContentControl such as this:
<ContentControl Content="{Binding SelectedPage" />
And DataTemplates would be used to tell WPF how to draw each section
<DataTemplate TargetType="{x:Type local:Page1ViewModel}">
<local:Page1View />
</DataTemplate>
<DataTemplate TargetType="{x:Type local:Page2ViewModel}">
<local:Page2View />
</DataTemplate>
<DataTemplate TargetType="{x:Type local:Page3ViewModel}">
<local:Page3View />
</DataTemplate>
I have not used a RibbonBar before, however it sounds like it should allow for an ItemsSource so your final XAML should probably look something similar to this:
<Window>
<Grid>
<DockPanel>
<RibbonBar ItemsSource="{Binding PageViewModels}"
SelectedItem="{Binding SelectedPageViewModel}"
DockPanel.Dock="Top" ...>
</RibbonBar>
<StackPanel>
<Grid>
... Generic Content
</Grid>
<ContentControl Content="{Binding SelectedPageViewModel}">
<ContentControl.Resources>
<DataTemplate TargetType="{x:Type local:Page1ViewModel}">
<local:Page1View />
</DataTemplate>
<DataTemplate TargetType="{x:Type local:Page2ViewModel}">
<local:Page2View />
</DataTemplate>
<DataTemplate TargetType="{x:Type local:Page3ViewModel}">
<local:Page3View />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</StackPanel>
</DockPanel>
</Grid>
</Window>
Content of your Shell.xaml:
<Window ...>
<StackPanel>
<Grid>
<!-- Your shared content -->
</Grid>
<ContentControl prism:RegionManager.RegionName="MainRegion"/>
</StackPanel>
</Window>

Is there a way to group RadioButtons generated from the ItemTemplate of an ItemsControl

<DataTemplate x:Key="Genre_DataTemplate">
<RadioButton GroupName="One" Content="{Binding...
</DataTemplate>
Above code is the ItemTemplate of my ItemsControl, I want all the Radiobuttons instantiated should behave as if it is in a group, I know the reason because the generated RadioButtons are not adjacent in the visualtree.
Any solution or workaround to group them together?. GroupName property also doesn't have any effect here.
[Update] I am trying this in Silverlight
The problem is that the RadioButton.GroupName behavior depends on the logical tree to find a common ancestor and effectively scope it's use to that part of the tree, but silverlight's ItemsControl doesn't maintain the logical tree. This means, in your example, the RadioButton's Parent property is always null
I built a simple attached behavior to fix this. It is available here: http://www.dragonshed.org/blog/2009/03/08/radiobuttons-in-a-datatemplate-in-silverlight/
I think the problem is somewhere else in the control tree. Can you post more details?
Here is a sample xaml code that works as expected:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Grid.Resources>
<XmlDataProvider x:Key="flickrdata" Source="http://api.flickr.com/services/feeds/photos_public.gne?tags=flower&lang=en-us&format=rss_200">
<XmlDataProvider.XmlNamespaceManager>
<XmlNamespaceMappingCollection>
<XmlNamespaceMapping Prefix="media" Uri="http://search.yahoo.com/mrss/"/>
</XmlNamespaceMappingCollection>
</XmlDataProvider.XmlNamespaceManager>
</XmlDataProvider>
<DataTemplate x:Key="itemTemplate">
<RadioButton GroupName="One">
<Image Width="75" Height="75" Source="{Binding Mode=OneWay, XPath=media:thumbnail/#url}"/>
</RadioButton>
</DataTemplate>
<ControlTemplate x:Key="controlTemplate" TargetType="{x:Type ItemsControl}">
<WrapPanel IsItemsHost="True" Orientation="Horizontal"/>
</ControlTemplate>
</Grid.Resources>
<ItemsControl
Width="375"
ItemsSource="{Binding Mode=Default, Source={StaticResource flickrdata}, XPath=/rss/channel/item}"
ItemTemplate="{StaticResource itemTemplate}"
Template="{StaticResource controlTemplate}">
</ItemsControl>
</Grid>
</Page>
P.S.: In order grouping to work elements radio buttons should have same parent (as they usually have when generated from ItemsControl)

Resources