In a WPF application, I would like to display a grid of tiles (buttons essentially) using images from a folder location. There could be any different number of images in the folder, so the tiles/buttons need to be generated dynamically and formatted based on the amount. These need to be buttons that can trigger mouse click events.
I'm very new to C# and .NET, so I'd just like some direction on what the best way of doing this would be. I've started this as a WPF application so would using a template be a good idea? Or if just dynamically creating form buttons with background images is an easy option then I'll give that a go.
You would probably need a ItemsControl such as a ListView. Unfortunately WPF only ships the GridView implementation, but the ListView was intended to support all those views you see in the Windows file explorer. For a Tiled based view you would need to override the ViewBase class and assign it to the View property of the ListView.
Years ago I have had sample code that demonstrated what you want.
The following link contains MSDN samples:
MSDN ListView.View samples
How to: Create a Custom View Mode
I know that the Xceed DataGrid has a built-in CardView mode. I don't know if it is available in the free version: Xceed WPF DataGrid documentation
Edit I just checked the MSDN samples and I think they are close to what you want.
I would go for ItemsControl. You need a class representing your buttons, with properties such as X, Y, ImageUri, and so on. You expose your generated buttons via ObservableCollection and bind it to ItemsSource of your ItemsControl. Then you change your ItemsPanelTemplate to grid:
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<!--Here go rows and columns definitions-->
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
If you have fixed number of rows and columns, you may add them directly in XAML, otherwise generate them at runtime in code-behind. You add ItemsContainerStyle for positioning:
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding Y}" />
<Setter Property="Grid.Column" Value="{Binding X}" />
</Style>
</ItemsControl.ItemContainerStyle>
Also, you need ItemTemplate which will cover displaying button with image. Other options would be to use Canvas or UniformGrid as ItemsPanelTemplate (both with their advantages and disadvantages).
Related
I'm using WPF (and the MVVM framework) to create an interface which has a slider on it.
<Slider Value="{Binding MotorDemandSpeed}" Maximum="3500" />
I'm trying to hide the track part on the slider so that you are left with just the 'thumb tack'. This is what the slider currently looks like (styles are controlled by a theme):
I've looked around at various methods, however I can't find a method that changes only a single slider.
Help is appreciated.
You need to set the Template property of this particular Slider instance to be able to override its ControlTemplate:
<Slider Value="{Binding MotorDemandSpeed}" Maximum="3500">
<Slider.Template>
<ControlTemplate TargetType="Slider">
<!-- define the custom template without a track here... -->
</ControlTemplate>
</Slider.Template>
</Slider>
In order to change the appearance of a control you will need to modify the control template. Each control is made up of many parts, and each part many objects. You can modify individual parts (such as the track) with the correct x:Key and TargetType.
This Question has an example of modifying a scrollbar control template, which is most likely similar to the template of this slider you have. The first step would be to identify the Xaml file in your theme which this slider uses and find the parts that define the trackbar, thumb, etc. From there you should be able to recreate the control to your liking, or just completely remove parts you do not need.
Are you using any third party controls that may have information on how to edit their themes? Perhaps try investigating Modifying Control Templates to get a better understanding of control templates.
Here is the MDSN page for the slider control template, you may find this useful.
Question:
Is there a way to achieve what I'm looking for; to simply add a collection of views (UserControls) to a control whilst having a consistent MVVM structure? Is an ItemsControl the way to go, or should be have a different approach?
Problem
I have a collection of MVVM projects (with usercontrol mainviews) that I want to present in another control that can animate transitions between them. I have a horizontal listbox across the top of the control functioning as 'tabs' which are bound to the collection of views. The main body of the control shows a single view bound to the selected item of the list box and animates transitions when a new tab is selected.
My concern is having the collection of views as part of the new control's viewmodel doesn't make much sense in the MVVM paradigm and it would be more usable if the usercontrols could simply by added straight into the control almost as if it was a panel. This would lead me to think something like ItemsControl is the way to go and could be used like this:
<CustomItemsControl>
<UserControl1>
<UserControl2>
<UserControl3>
<UserControl4>
</CustomItemsControl>
Then have content that looked something like this.
<ItemsControl.Template>
<StackPanel>
<ListBox x:Name="Tabs" Height="35" SelectedIndex="0"
ItemsSource= >> The binding for the ItemsControls Collection <<
SelectionChanged="Tabs_TabSelected">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1"
Columns= >> Binding to Collection.Count <<
/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
<TransitionCtrl Name="TransitionControl" CurrentView="{Binding SelectedItem, ElementName=Tabs}" />
</StackPanel>
</ItemsControl.Template>
From the examples I've looked at the ItemsControl isn't intended to be used in this way. Any suggestions to point me in the direction of what I'm trying to achieve?
You should be using PRISM view injection technique. The best approach would be using TabControl as a region and inject the main view when each module loaded. Since tab is not built as a region, you may need a custom region adapter as explained here.
<TabControl Grid.Row=”1″ Grid.Column=”1″
cal:RegionManager.RegionName=”TabRegion” Name=”TabRegion”>
From every module,
public void Initialize()
{
regionManager
.AddToRegion(“TabRegion”, new FirstView())
.AddToRegion(“TabRegion”, new SecondView());
}
In WPF (VS2013), I'm creating a button like so:
<Button>
<Label>1</Label>
</Button>
Each of these buttons will have more to it, such as increased font size of the Label, grid row/column assignment, and I might use a binding for the label so that I can change the number. I'm creating a calculator app so I need to reuse this button 10 times (one for each number 0-9). Instead of copying/pasting this button XML 10 times, I wanted to see if I could templatize it.
I've read a little about ControlTemplate and DataTemplate, but I'm not sure if either of these are the correct thing to use. It's also not clear to me what should be a style or what should be a template.
So if someone could help me understand how to "templatize" the button and its styles (e.g. width, height, font size, etc) so that they can be easily reused, that would help a ton. Guidance is appreciated!
Use a ControlTemplate when you want to overwrite the entire template for a control, use a DataTemplate when you want to tell WPF how to draw a data object (usually the DataContext), and use ContentTemplate when you want to tell WPF how to draw the Content property of an object.
Creating a whole new ControlTemplate is quite complex. To demonstrate, check out this MSDN example for an example ControlTemplate for a Button.
In your case, I would recommend creating a Style for your button with setters for common properties such as Height, Width, Font, etc. If you want to draw your button's Content property in a custom way without completely overwriting the button template, include a ContentTemplate style setter to tell WPF how to draw the Button.Content property.
<Button Style="{StaticResource CalculatorButton}" Content="1" />
and
<Style x:Key="CalculatorButton" TargetType="{x:Type Button}">
<Setter Property="Height" Value="50"/>
<Setter Property="Width" Value="50"/>
<Setter Property="FontSize" Value="14" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding }" FontFamily="Wingdings 3" FontWeight="Bold" FontSize="18" Foreground="Navy" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
The ControlTemplate defines how the button looks, the ContentTemplate defines how the Button.Content looks, and the DataTemplate used for the ContentTemplate is defining how the data object of "1" will be drawn.
You can start with a copy of the style of the button. Use Blend (part of VS) to create that: open the context menu of the button inside the object tree, then select "Edit template" (or similar, don't have an english version at hand), then "Copy of template" (or alike).
Now you may change properties (in designer or XAML). Every button that shall have this style needs to reference this new ressource.
You need to create a new Style of a button. Learning curve is not too steep, but the benefits are enormous. You can start learning about it here: http://msdn.microsoft.com/en-us/library/ms745683(v=vs.110).aspx
Long story short: Open your project with Blend, right-click on your button, "Edit Style", "Edit a copy". If you choose to define it in Application, you can reuse it among other pages (it will be then in you App.xaml file)
Once you have the base style, edit it as much as you need.
When my app is snapped displaying a GridView isn't the best way to present the information. I want to present it in a ListView instead. I also want to change the item template as well.
I currently have a UserControl that accepts the DataContext as the item template so I can simply create a new view and use that instead and it should work. So I'm basically looking to swap local:NormalDetailView with local:SnappedDetailView
Originally I thought about having both the ListView and GridView in there at the same time and adjusting the visibility based on snapped mode. But I had doubts about the performance about this technique.
Lastly, this is a LayoutAwarePage so I do have all that XAML stuff at the bottom about VisualStateManager.VisualStateGroups etc.
<GridView x:Name="GalleryGridView"ItemsSource="{Binding ListOfItems}">
<GridView.ItemTemplate>
<DataTemplate>
<local:NormalDetailView VerticalAlignment="Center" Width="250" Height="250" DataContext="{Binding}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
The performance is just fine if you use both a gridview and a listview, and adjust visibility depending on view state. This is exactly what the "split-application" template in Visual Studio does.
Just generate an app based on this template and take a look at ItemsPage.xaml and ItemsPage.xaml.cs. The other templates may also do this, but I haven't used them so I don't know for sure.
Is there a way to change the style of checkboxes when the ItemsOptionListType="CheckList"
inside a RadTreeView?
There are a couple of ways of doing this that I can think of, but sadly neither of them is particularly easy.
One way is to use Blend or a similar tool to obtain the template for the RadTreeViewItem class. The RadTreeViewItem class and its template are in the Telerik.Windows.Controls.Navigation assembly. Take a copy of this template and modify the CheckBox within this template to customise its appearance as you wish.
To use the template, add a ControlTemplate and a Style to the <UserControl.Resources> element of a XAML page, as follows:
<UserControl.Resources>
<ControlTemplate x:Key="myRadTreeViewItemTemplate" TargetType="telerik:RadTreeViewItem">
<!-- modified template goes here... -->
</ControlTemplate>
<Style TargetType="telerik:RadTreeViewItem">
<Setter Property="Template" Value={StaticResource myRadTreeViewItemTemplate}" />
</Style>
</UserControl.Resources>
This should then apply the modified template to any RadTreeViews in the same XAML file.
Note that we have to use an implicit style (i.e. one without an x:Key), since there seems to be no other way to tell a RadTreeView to apply a given style to its child items.
Alternatively, you can modify a built-in theme. This approach could also change the styles of CheckBoxes used within other Telerik controls in your application, for example in a GridViewCheckBoxColumn within a RadGridView.
EDIT: if you want the template for the CheckBox as used in the RadTreeView by default,
you'll find it in Themes\Office\Black\System.Windows.Controls.xaml within the Telerik.Windows.Controls assembly. This assumes you're using the 'Office Black' theme; adjust the path of this file if you're using a different Telerik theme.