I made a custom control called SmartTabItem, currently just the default implementation:
using System.Windows;
using System.Windows.Controls;
namespace TestControl.Controls
{
public class SmartTabItem : TabItem
{
static SmartTabItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SmartTabItem), new FrameworkPropertyMetadata(typeof(SmartTabItem)));
}
}
}
I include it in my TabControl like this:
<Window x:Class="TestControl.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:TestControl.Controls"
Title="Window1" Height="300" Width="300">
<DockPanel Margin="10">
<TabControl>
<controls:SmartTabItem Header="One">content of one</controls:SmartTabItem>
<TabItem Header="Two">content of two</TabItem>
<TabItem Header="Three">content of three</TabItem>
</TabControl>
</DockPanel>
</Window>
But only tabs "Two" and "Three" are displayed. Why isn't the SmartTabItem showing up in the TabControl if it inherits from TabItem?
To use the default style for a TabItem on your SmartTabItem, modify the code like this:
DefaultStyleKeyProperty.OverrideMetadata(typeof(SmartTabItem), new FrameworkPropertyMetadata(typeof(TabItem)));
This will tell the wpf system to use the TabItem's default style for your tab items. Otherwise, your tab item is truly lookless.
I'm guessing because you've overridden its default style, but have not provided a style for it in Generic.xaml. Try commenting out this line to test:
DefaultStyleKeyProperty.OverrideMetadata(typeof(SmartTabItem), new FrameworkPropertyMetadata(typeof(SmartTabItem)));
Related
I'm trying to refactor the property MyText to a new name HerText in the following solution:
MainWindow.xaml.cs
using System.Windows;
namespace resharper_refactoring_xaml
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MyText = "Blabla";
DataContext = this;
}
public string MyText { get; set; }
}
}
MainWindow.Xaml
<Window x:Class="resharper_refactoring_xaml.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:resharper_refactoring_xaml"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBlock Text="{Binding Path=MyText}"></TextBlock>
</Grid>
</Window>
I right click on the property and select Refactor this > Rename. Then I type in a new name for the property, hit Next.
Unfortunately, only the references of MyText in the code-behind are renamed. References to MyText in the XAML file rename intact.
According to this question Resharper should be able to propagate refactorings to XAML files.
Why is the rename not propagating to the XAML file? Is there some sort of Resharper setting I might have overlooked?
The reason behind this seems to be that ReSharper cannot determine that the property name specified in the XAML markup refers to the property defined in the MainWindow class, if the DataContext property is set in code-behind.
Bindings refer to the DataContext of controls as source by default. If it is not detected, the link between the loose markup and the defining type is lost. I cannot tell if this is a bug in ReSharper or a general limitation.
However, there are two simple solutions to this issue that work for me:
Set a design time data context to the type that defines the property here MainWindow.
<Window ...
d:DataContext="{d:DesignInstance Type={x:Type local:MainWindow}}">
Set the data context via binding in XAML instead of code-behind.
<Window ...
DataContext="{Binding RelativeSource={RelativeSource Self}}">
Hello I am using Prism in my demo project and I have a problem with user controls' inheritance. If I use my user control base class for my user control like below, user control's content is showing up empty. Then when I use
<igf:UserControlBase x:Class="DemoProject.Views.DemoView"
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:igf="http://igf.schema"
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="200">
<StackPanel>
<TextBox Text="Hello Prism"/>
<TextBlock Text="Hello Prism"></TextBlock>
</StackPanel>
</igf:ViewControlBase>
and this is my user control and it is in another project. And ctors are commented now but still not working. Only way is changing
using System.Windows;
using System.Windows.Controls;
namespace DemoProject.Base.Controls
{
public class UserControlBase : UserControl
{
static UserControlBase()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(UserControlBase), new FrameworkPropertyMetadata(typeof(UserControlBase)));
}
public UserControlBase()
{
DefaultStyleKey = typeof(UserControlBase);
}
}
}
I found solution by adding code below into Assembly.cs file to user control's project
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
Originally I had my MainWindow(.xaml) that had a stackpanel and a frame. Within the stackpanel were three navigation buttons and the frame had one of the three Pages (based on which navigation button the user clicked). However, it seems that since I'm not doing a web app, that using Frame (and Pages?) is not the right way to go about it. So I changed the stackpanel and frame to a single tabcontrol (with tabs being what were the three buttons before). I also changed the Pages to usercontrols.
However, I'm having trouble finding a way to put the Pages (now UserControls) into the content of the tabitem, without using a Frame. I'm trying to do all of this within the MainWindow xaml.
my MainWindow.xaml:
<Window x:Class="ConstructedLanguageOrganizerTool.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Height="454" Width="573">
<Grid>
<TabControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Name="tabControl1">
<TabItem Header="Basics" Name="basicsTab">
//What can I use here instead of Frame?
</TabItem>
<TabItem Header="Words" Name="wordsTab">
<Grid>
<Frame Source="WordsPage.xaml"/>
</Grid>
</TabItem>
...
</TabControl>
</Grid>
</Window>
Am I going about this the wrong way? I think that I'm suppose to use some sort of databinding, maybe? Although, the more I look at things on data binging, the more I just get confused on that as well.
edit: here is my BasicsPage.xaml
<UserControl x:Class="ConstructedLanguageOrganizerTool.BasicsPage"
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" x:Name="basicsPage" Height="349" Width="334">
<Grid>
// Grid Row and Column defs here
//Number of textboxs and textblocks here.
</Grid>
</UserControl>
You just need to create an instance of UserControl and put it inside TabItem.
Say BasicsPage is your UserControl you want to put inside TabItem. All you have to do this:
<TabItem Header="Basics" Name="basicsTab">
<local:BasicsPage/>
</TabItem>
Define local namespace at root window where BasicsPage is defined in something like:
<Window x:Class="ConstructedLanguageOrganizerTool.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ConstructedLanguageOrganizerTool"> <-- HERE
I have a class named MyWindow that derives from Window:
using System.Windows;
public class MyWindow : Window
{
}
And I use that class in MainWindow.xaml:
<MyWpfApp:MyWindow x:Class="MyWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:wpfApplication1="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock Text="Test" Foreground="Orange"/>
</Grid>
</MyWpfApp:MyWindow>
And in the App.xaml file, I add the following style to override the Background property of all MyWindow instances:
<Application.Resources>
<Style TargetType="MyWpfApp:MyWindow">
<Setter Property="Background" Value="Black"></Setter>
</Style>
</Application.Resources>
But this doesn't change anything at all. No style is applied to MainWindow.
What should I do so that I can use a global style for all MyWindows?
P.S.: I checked out "Modern UI"s code, I saw that they apply something like the following in their window's constructor:
using System.Windows;
public class MyWindow : Window
{
public MyWindow()
{
DefaultSyleKey = typeof (MyWindow);
}
}
But if I do this, MainWindow ends up being completely black in the content area. I am guessing that somehow its Template property gets overriden, but I don't understand how, and how to make this work.
Ok I have worked it out. Apparently there's a special file you can use named generic.xaml.
You need to add your style definitions there and then add that file to a directory called Themes.
WPF will end up using that as a fall back: Themes\generic.xaml
It doesn't seem like the Caliburn Micro framework is retrieving my SinglePaintToolbarView when it is binded as a list of buttons in the toolbar of the ShellView. I would like the buttons to just display their text content when they are added to the toolbar. But, instead I'm getting this:
There doesn't appear to be any clickable buttons in the toolbar. I know my plugins are being loaded successfully, because I was able to bind one of the plugins in the list as a ContentControl and the view appeared. It just doesn't seem to work when I try to bind a list of the plugins in a toolbar.
Here is what I have:
ShellView.xaml
<UserControl x:Class="Starbolt.Views.ShellView"
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>
<ToolBarTray>
<ToolBar ItemsSource="{Binding Path=ToolbarPlugins}"/>
</ToolBarTray>
</Grid>
</UserControl>
ShellViewModel.cs
[Export(typeof(IShell))]
public class ShellViewModel : PropertyChangedBase, IShell
{
[ImportMany(typeof(IToolbarPlugin))]
private IEnumerable<IToolbarPlugin> _toolbarPlugins = null;
public IEnumerable<IToolbarPlugin> ToolbarPlugins { get { return _toolbarPlugins; } }
}
SinglePaintToolbarView.xaml
<UserControl x:Class="Starbolt.Plugin.SinglePaintTool.Views.SinglePaintToolView"
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="128" d:DesignWidth="32">
<Button Name="btnSinglePaintTool" Content="Single Paint Tool" Width="128" Height="32"/>
</UserControl>
SinglePaintToolViewModel.cs
[Export(typeof(IToolbarPlugin))]
public class SinglePaintToolViewModel : IToolbarPlugin
{
}
Basically, your design seems to be working. If you replace
<ToolBarTray>
<ToolBar x:Name="ToolbarPlugins"/>
</ToolBarTray>
(note that you do not need to bind the ItemsSource explicitly, you can just as well use the Caliburn Micro property name conventions) with the following:
<ListBox x:Name="ToolbarPlugins"/>
the SinglePaintToolView button is displayed as intended.
I suspect that the problem is with the ToolBar ControlTemplate, which most certainly restricts the toolbar items layout more than what for example a ListBox ControlTemplate does.
So my guess is that if you really want to use the ToolBar control to display your IToolbarPlugin views, you will probably have to design a dedicated ToolBar control template in your project.
Alternatively, you could implement a toolbar replacement using e.g. ListBox. This could be a start:
<ListBox x:Name="ToolbarPlugins">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>