I have a WP7 app that is using bing maps and I have pushpins for multiple locations. On tapping the pushpin I have a tap event that displays a border with some text. To hide the text I’m using a tap event for the map control which sets the border visibility to collapsed:
private void map_Tap(object sender, GestureEventArgs e)
{
this.border.Visibility = Visibility.Collapsed;
}
Now if I am going to be using multiple borders and texts, I’m going to have to set the visibility multiple times like so:
this.border.Visibility = Visibility.Collapsed;
this.border2.Visibility = Visibility.Collapsed;
this.border3.Visibility = Visibility.Collapsed;
So I created a resource for the border in order to refer to just one border.
<phone:PhoneApplicationPage.Resources>
<Style x:Key="BorderStyle" x:Name="border" TargetType="Border" >
<Setter Property="Background" Value="Black" />
</Style>
</phone:PhoneApplicationPage.Resources>
And I set the resource in the pushpin
<my:Pushpin.Content>
<Border Style="{StaticResource BorderStyle}" >
But now when I refer to the border in the map_Tap event I get a System.Windows.Style does not contain a definition for ‘Visibility’ because the border is no long referenced as a UIElement(at least that’s how I’m understanding this). How can a make a style for the border element and still reference it as an element?
I would like to suggest you this approach and this might help you for some other tasks too.
You use a list of type border and add all the border elements into it. Now whenever you want to manipulate all the elements you can have a foreach loop and access any property you would like example item.Visibility and you can manipulate it as you like. This will even help you sort them out so that you can manipulate any specific border.
Related
I have a ListBox using a Panel as its ItemsPanel
What I would like to do is load the bytes for an image into the bound property in the view model for each ListBoxItem that is currently on screen, and unload the bytes when they are scrolled off screen.
I have tried Panel.OnVisualChildrenChanged. This tells me when items are added or removed to the panel, but doesn't seem to help my specific case.
I have tried
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="RequestBringIntoView" Handler="EventSetter_OnHandler" />
</Style>
That event never seems to fire. edit: fires when item is selected
I have also gotten a reference to the ListBox ScrollViewer to look at the VerticalOffset and Viewport.Height/Width but I don't see how that information helps me.
I have an application, which uses WPF on windows as toolkit framework. Now I would like to set the width of scrollbars for my ScrollViewers programmatically. I found many examples to set the width via XAML. But how can I define the width of scrollbars programmatically?
Unfortunately I could not find any property or method on ScrollViewer to set the width of scrollbars.
var viewer = new ScrollViewer();
viewer.MagicProperty = 42; // Does not exist
Also all properties on SystemParameters are unfortunately read-only.
VerticalScrollBarWidth.VerticalScrollBarWidth = 42; // Read-only
Edit: WPF is only one of multiple toolkit frameworks in my application. I use a custom GUI abstraction layer for supporting Windows (WPF), Linux (GTK#) and MacOS X (in future). My user interface is encapsulated in an OS independent way. Therefore it makes no sense to use XAML.
Easiest way is to set x:Name property, then you can access ScrollViewer in your code.
Or use Binding: http://www.tutorialspoint.com/wpf/wpf_data_binding.htm
Binding will be useful if you want to manipulate with multile ScrollViewers and set same values.
EDIT:
You can create ScrollViewer in your code and then set its parameters. But you need a way to insert it into VisualTree among other controls. So you need to get instance of some container and then use its Children.Add() method
However I'd really recommend to use as much XAML as you can and leave your code for application logic, not the UI building.
EDIT 2:
Can you try:
Style myStyle = new Style(typeof(ScrollBar));
myStyle.Setters.Add(new Setter(WidthProperty, 40));
scrollViewer.Style = myStyle;
EDIT 3:
I found a solution. You can add ResourceDictionary.xaml and add this style to it:
<Style x:Key="{x:Type ScrollBar}" TargetType="{x:Type ScrollBar}">
<Setter Property="MinWidth" Value="35" />
<Setter Property="Width" Value="35" />
</Style>
Then load it at runtime like so:
Resources.MergedDictionaries.Add(Application.LoadComponent(new Uri(#"Dictionary.xaml", UriKind.Relative)) as
ResourceDictionary);
I'm working with Fluent.Ribbon, and I am desperately trying to vertically center the text of second level menu items. I actually wouldn't mind making second level have the same style as first level items if that would be easier.
From digging through the source code, I think I've found that the separate style is defined by the ControlTemplate ApplicationMenuSecondLevelItemTemplate. However, since I'm working on learning WPF, I'm not sure how to override that with styles.
I've tried simpler solutions, like this one which just makes the text disappear.
I've also tried all of the option in this post. However, none of those work either, and when I fix the last one to be the following to get rid of errors, the application just crashes.
<Style x:Key="CenteredTextMenuItem" TargetType="{x:Type MenuItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding}" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center" FontSize="16" FontWeight="Bold"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Height" Value="30"/>
<Setter Property="Width" Value="188"/>
</Style>
How can I center a second level MenuItem's text with the Fluent.Ribbon control?
Thanks.
Edit:
Here is an image showing how the second level is not centered.
And nothing complicated with the code:
<Fluent:MenuItem Header="Print Invoice" Icon="NavIcons\Print_32.png" />
Here are possible solutions for your problem.
Simple, but somewhat ugly.
Create an event handler in code behind for the Loaded event of your menu items.
<Fluent:MenuItem Loaded="MenuItem_Loaded"/>
In this event handler, you can find the control template parts manually and override their appearance:
private void MenuItem_Loaded(object sender, RoutedEventArgs e)
{
Fluent.MenuItem menuItem = sender as Fluent.MenuItem;
if (menuItem != null)
{
TextBlock textBlock = menuItem.Template.FindName("textBlockDesc", menuItem) as TextBlock;
if (textBlock != null)
{
textBlock.Visibility = System.Windows.Visibility.Collapsed;
}
textBlock = menuItem.Template.FindName("textBlock", menuItem) as TextBlock;
if (textBlock != null)
{
textBlock.VerticalAlignment = System.Windows.VerticalAlignment.Center;
}
}
}
This is a bad solution, don't do it like that. I've just shown it so you can get an idea how could you access the template parts if you wish to. These strings "textBlockDesc" and "textBlock" are the control template parts defined in the Fluent theme.
Create your own style and control template.
Since you can't inherit a control template, you have to copy it from the Fluent theme and put it in your resources. The disadvantage is that you'll have to manually resync that template with the original one if there will be an update.
I don't put an example here, because that solution isn't really good too.
Override the menu item style manually.
Set the style of your menu items manually to the "first level" menu items' style.
<Fluent:MenuItem Style="{DynamicResource ApplicationMenuStyle}"/>
I am trying to setup a windows.resoruces style that targets all textbox's within all groupbox's (so it would not target textbox's that are not found within a groupbox)
I know I could use the x:key field, but was wondering if there was a way to target certain controls within controls for an entire window or application?
You could try a nested style for your TextBoxes in Style.Resources of GroupBox with Style.TargetType but without x:key.
<Style TargetType="GroupBox">
<Style.Resources>
<Style TargetType="TextBox">
...
</Style>
</Style.Resources>
</Style>
One trick you could use is to define Textbox style without the x:key field. This one will apply to all the TextBoxes that do not have a Style specified.
Use this Style for the TextBoxes within the GroupBoxes by not using the Style Tag on these Boxes and for all other TextBoxes use a specific named Style by using the Style tag...
I saw a similar question and hoped for a solution, but simply giving an advice to subclass the ComboBox is not enough for me. I need it in small spoons...
The case is I need an extra button on my special comboBox for adding new records to the item list. I have this as an UserControl today but it doesn't look good and I need more controls on my views, so I started making a custom control trying to extend ComboBox.
I didn't get far... Please lend me a hand... :)
My code so far:
public class ComboBoxWithAdd : ComboBox
{
static ComboBoxWithAdd()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ComboBoxWithAdd), new FrameworkPropertyMetadata(typeof(ComboBoxWithAdd)));
}
}
In Generic.xaml I have this:
<Style TargetType="{x:Type local:ComboBoxWithAdd}" BasedOn="{StaticResource {x:Type ComboBox}}">
</Style>
When making the decision to create a custom control you need to determine whether you need to add actual behavior or just UI. Just adding a button can be done by just customizing the ControlTemplate. It sounds like you want a button that causes an action that will update the Items of the ComboBox which would point to the direction you started down of deriving a control from ComboBox. You'll need to add a few things on the code and XAML side. In your Style you'll need to add a Setter for the ControlTemplate and start with a copy of the default template for ComboBox (I usually do this with Blend but there are other sources out there). You can then add in your new Button wherever you want it in the template.
<Style TargetType="{x:Type local:ComboBoxWithAdd}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ComboBoxWithAdd}">
... copy of default template with your modifications
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
There are a few different ways you could connect the button but the most robust is to use a command that you can bind to in your control code. You can declare your own RoutedCommand in your control code later but to get started just use a built in one.
public ComboBoxWithAdd()
{
CommandBindings.Add(new CommandBinding(ApplicationCommands.New, NewExecutedMethod));
}
Then in the NewExecutedMethod just add whatever logic you want to do the actual action to add an item (probably working with the ComboBox's Items/ItemsSource). To connect the button up just set Command="ApplicationCommands.New". There's a lot more that can be done with a custom control but this should get you started.
Rozon, You can manipulate the Combobox from the code behind like this without creating a complex template:
public class CustomComboBox : ComboBox
{
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Grid grid = WpfHelper.FindAllChildrenByName<Grid>(this, "MainGrid").SingleOrDefault() as Grid;
if (grid != null)
{
grid.ColumnDefinitions.Add(new ColumnDefinition());
Button button = new Button();
button.Content = "test";
button.SetValue(Grid.ColumnProperty, 2);
grid.Children.Add(button);
}
}
}
WpfHelper is just a class which finds a visual child by its name. Notice that this might break easily if the standard control template of the combobox is changed and MainGrid is renamed.
I would suggest you to use the UserControl that you created by adding one more button and grouped them to make a user control and exposing the required events and commands.
Custom control is not advisable.
But, if you have requirement like that. Here we go:
1) You need to derive the control for what you are trying to extend the capability.
2) You need to create a default Template for the control. [Generic.Xaml]
Rest is your customization.
But, one advantage is you could get a easily Skinnable control.
HTH