I have an CustomControl with a ControlTemplate like this:
<ControlTemplate x:Key="ListBoxInputControl" TargetType="{x:Type cc:InputControl}">
<Grid
x:Name="ListRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Labels"/>
<ColumnDefinition Width="120"/>
</Grid.ColumnDefinitions>
<Label...
</Label>
<ListBox
x:Name="PART_ListBox"
Grid.Column="1"
ItemsSource=.... // what goes here?
ItemTemplate="{TemplateBinding ListBoxItemTemplate}"
Foreground="{TemplateBinding LblForeground}"
Background="{TemplateBinding LblBackground}"
SelectedItem="{TemplateBinding CbSelectedItem}">
</ListBox>
</Grid>
</ControlTemplate>
I need to link an XmlDataProvider to the ItemsSource through a Dependency Property "CbItemsSource".
This is what I have so far:
<ListViewItem>
<ListViewItem.Resources>
<XmlDataProvider x:Key="CrossSection" XPath="CheckList">
<x:XData>
<CheckList xmlns="">
<ListNode Title="Circ"/>
<ListNode Title="Oct"/>
</CheckList>
</x:XData>
</XmlDataProvider>
</ListViewItem.Resources>
<local:InputControl
Template="{StaticResource ListBoxInputControl}"
ListBoxItemTemplate ="{StaticResource ListNodeTemplate}"
CbItemsSource="{Binding Source={StaticResource CrossSection}, XPath=//ListNode, Mode=TwoWay}"
LvSelectedIndex=...../>
</ListViewItem>
But that does not work.
I get an error:
Error No matching constructor found on type 'System.Xml.Serialization.IXmlSerializable'.
You can use the Arguments or FactoryMethod directives to construct this type.
I think the source binding in the line "CbItemsSource="{B..." is the problem.
What must I do?
Related
In a WPF application and using the Fluent Ribbon Control Suite, I have a DropDownButton that opens up a Gallery that lets the user select a color.
Here is the XAML that creates the button:
<Fluent:DropDownButton x:Name="btnCommentColor" Header="Comments">
<Fluent:DropDownButton.Icon>
<!-- What goes here? -->
</Fluent:DropDownButton.Icon>
<Fluent:Gallery x:Name="galCommentColor" ItemsSource="{Binding Source={StaticResource colorPropertiesOdp}}" SelectedValuePath="Name" MaxItemsInRow="12">
<Fluent:Gallery.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" CornerRadius="2" BorderBrush="Black" Width="25" Height="25" VerticalAlignment="Stretch" Background="{Binding Name}" />
</DataTemplate>
</Fluent:Gallery.ItemTemplate>
</Fluent:Gallery>
</Fluent:DropDownButton>
The SelectedItem of the Gallery returns the Name of the color. I want to make the Icon of the button display the actual color that was selected. Can this be done purely with XAML? I have been trying various things found online but so far have been unable to get anything other than the color name to appear where I want the color rectangle to go. Look for the "What Goes Here?" in the XAML above.
I appreciate any helpful suggestions. Thanks for reading!
UPDATE:
I tried the answer given below and it still doesn't work. I must have something wrong. Here's an updated listing of all the XAML code for this button. Take a look at the XAML for the Gallery itself and the binding for the SolidColorBrush and tell me if you see what i've done wrong.
<Window.Resources>
<ObjectDataProvider MethodName="GetType"
ObjectType="{x:Type sys:Type}" x:Key="colorsTypeOdp">
<ObjectDataProvider.MethodParameters>
<sys:String>System.Windows.Media.Colors, PresentationCore,
Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35</sys:String>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider ObjectInstance="{StaticResource colorsTypeOdp}"
MethodName="GetProperties" x:Key="colorPropertiesOdp">
</ObjectDataProvider>
</Window.Resources>
<Fluent:DropDownButton Name="btnCommentColor" Header="Comments">
<Fluent:DropDownButton.LargeIcon>
<Grid Width="32" Height="32">
<Image Source="Icons\BlueLarge.png" />
<Border Height="32" VerticalAlignment="Bottom" BorderThickness="0" CornerRadius="2">
<Border.Background>
<SolidColorBrush Color="{Binding ElementName=galCommentColor, Path=SelectedValue, FallbackValue=Green}" />
</Border.Background>
</Border>
</Grid>
</Fluent:DropDownButton.LargeIcon>
<Fluent:Gallery Name="galCommentColor" ItemsSource="{Binding Source={StaticResource colorPropertiesOdp}}" SelectedValuePath="Name" MaxItemsInRow="12">
<Fluent:Gallery.ItemTemplate>
<DataTemplate>
<Border ToolTip="{Binding Path=Name}" BorderThickness="1" CornerRadius="2" BorderBrush="Black" Width="25" Height="25" VerticalAlignment="Stretch" Background="{Binding Name}" />
</DataTemplate>
</Fluent:Gallery.ItemTemplate>
</Fluent:Gallery>
</Fluent:DropDownButton>
On the page 17 of the walkthrough you have an example of what you are trying to achieve.
You can download it here : http://fluent.codeplex.com/documentation
Taken from the walkthrough :
<fluent1:Ribbon>
<fluent1:Ribbon.Menu>
<fluent1:Backstage />
</fluent1:Ribbon.Menu>
<fluent1:RibbonTabItem Header="Home">
<fluent1:RibbonGroupBox Header="Clipboard">
<!-- The following code shows standard mode for color gallery -->
<fluent1:DropDownButton Header="Standard">
<!-- It's possible to create custom icon to present selected color -->
<fluent1:DropDownButton.Icon>
<Grid Width="16" Height="16">
<Image Source="Images\FontColor.png" />
<Border Height="4"
VerticalAlignment="Bottom"
BorderThickness="0">
<Border.Background>
<SolidColorBrush
Color="{Binding ElementName=ColorGalleryStandard, Path=SelectedColor, FallbackValue=Black}" />
</Border.Background>
</Border>
</Grid>
</fluent1:DropDownButton.Icon>
<fluent1:ColorGallery x:Name="ColorGalleryStandard"
IsNoColorButtonVisible="False"
SelectedColor="Red" />
<fluent1:MenuItem Header="A Menu Item" Icon="Images\Pink.png" />
</fluent1:DropDownButton>
</fluent1:RibbonGroupBox>
</fluent1:RibbonTabItem>
</fluent1:Ribbon>
UPDATE
I see nothing wrong in your code, I've pasted it and it ran successfully, here is it again pasted from my working test.
<Window x:Class="WpfApplication8.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:fluent1="clr-namespace:Fluent;assembly=Fluent"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="MainWindow"
Width="525"
Height="350">
<Window.Resources>
<ObjectDataProvider x:Key="colorsTypeOdp"
MethodName="GetType"
ObjectType="{x:Type system:Type}">
<ObjectDataProvider.MethodParameters>
<system:String>
System.Windows.Media.Colors, PresentationCore,
Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35
</system:String>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider x:Key="colorPropertiesOdp"
MethodName="GetProperties"
ObjectInstance="{StaticResource colorsTypeOdp}" />
</Window.Resources>
<fluent1:DropDownButton Name="btnCommentColor" Header="Comments">
<fluent1:DropDownButton.LargeIcon>
<Grid Width="32" Height="32">
<Image Source="Icons\BlueLarge.png" />
<Border Height="32"
VerticalAlignment="Bottom"
BorderThickness="0"
CornerRadius="2">
<Border.Background>
<SolidColorBrush
Color="{Binding ElementName=galCommentColor, Path=SelectedValue, FallbackValue=Green}" />
</Border.Background>
</Border>
</Grid>
</fluent1:DropDownButton.LargeIcon>
<fluent1:Gallery Name="galCommentColor"
ItemsSource="{Binding Source={StaticResource colorPropertiesOdp}}"
MaxItemsInRow="12"
SelectedValuePath="Name">
<fluent1:Gallery.ItemTemplate>
<DataTemplate>
<Border Width="25"
Height="25"
VerticalAlignment="Stretch"
Background="{Binding Name}"
BorderBrush="Black"
BorderThickness="1"
CornerRadius="2"
ToolTip="{Binding Path=Name}" />
</DataTemplate>
</fluent1:Gallery.ItemTemplate>
</fluent1:Gallery>
</fluent1:DropDownButton>
</Window>
Thanks to Aybe for confirming that it's not me. I did get the result I wanted by using a converter on the LargeIcon property of the DropDownButton.
Here's the XAML:
<Fluent:DropDownButton Name="btnCommentColor" Header="Comments" HasTriangle="False" LargeIcon="{Binding ElementName=galCommentColor, Path=SelectedValue, Converter={StaticResource ColorNameToBorderConverter_Key}}">
<Fluent:Gallery x:Name="galCommentColor" ItemsSource="{Binding Source={StaticResource colorPropertiesOdp}}" SelectedValuePath="Name" MaxItemsInRow="12" SelectedIndex="51">
<Fluent:Gallery.ItemTemplate>
<DataTemplate>
<Border ToolTip="{Binding Name}" BorderThickness="1" CornerRadius="2" BorderBrush="Black" Width="25" Height="25" VerticalAlignment="Stretch" Background="{Binding Name}" />
</DataTemplate>
</Fluent:Gallery.ItemTemplate>
</Fluent:Gallery>
</Fluent:DropDownButton>
And the code:
Public Class ColorNameToBorderConverter
Implements IValueConverter
Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert
If ApplicationIsInDesignMode Then value = "Black"
If TypeOf value Is String Then
Return New Border With {
.Height = 32,
.BorderThickness = New Thickness(1),
.BorderBrush = New SolidColorBrush(System.Windows.Media.Colors.Black),
.CornerRadius = New CornerRadius(2, 2, 2, 2),
.VerticalAlignment = VerticalAlignment.Bottom,
.Background = New SolidColorBrush(ColorConverter.ConvertFromString(value))
}
Else
Throw New InvalidOperationException("Unsupported type [" & value.GetType.ToString & "]")
End If
End Function
Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
Throw New NotImplementedException
End Function
Private Shared ReadOnly Property ApplicationIsInDesignMode() As Boolean
Get
Return CBool(DesignerProperties.IsInDesignModeProperty.GetMetadata(GetType(DependencyObject)).DefaultValue)
End Get
End Property
End Class
I am new to WPF binding/templating. I have some basic questions about a templated TabControl I have as below :
<TabControl x:Name="tcTabs" ItemsSource="{Binding Rooms, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Margin="5" BorderThickness="1" IsSynchronizedWithCurrentItem="True">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding Name}" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="130"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="22"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Grid.Column="0" BorderThickness="0" ItemsSource="{Binding Messages}" DisplayMemberPath="Raw" />
<ListBox Grid.Row="0" Grid.Column="1" BorderThickness="1,0,0,0" BorderBrush="#FFBBBBBB" ItemsSource="{Binding Users}" DisplayMemberPath="Nick" />
<TextBox Grid.Row="1" Grid.ColumnSpan="2" BorderThickness="0,1,0,0" BorderBrush="#FFBBBBBB" Height="22" />
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
The TabControl contains in each tab 2 list boxes and a textbox. One of the listboxes contains user names is is not necessary all the time.
There are 3 kinds of tabs, Server tabs, room tabs and private tabs. In private and server tabs the user list should not exist or be hidden.
I have an enum on the bound room object :
public enum IRCRoomType
{
Server,
Channel,
Private
}
How do I automatically hide the user list based on the enum, I have seen samples of 2 approaches, the binding on visibility with a converter or a trigger. Which is the better approach and are there any more?
When there are no tabs, and the first tab is created it is not automatically selected, how do I select it?
Is there a way of impacting the item styles inside the listboxes depending on tab type? How would I acheive this?
I am just looking for links/hints and not for actual solutions, but if you can give code then that would be a bonus!
It depends on how complicated code. If it's simple I rather use Trigger (you have everything which belows to UI in XAML), but if code is much more complicated consider using Converters (It's actually simpler to use it)
Bind to SelectedIndex of List and set it to 0?
Yes, of course, you can use ContentControl with DataTemplate (Or just DataTemplate in some cases) Some code where I use it:
<ListBox>
<ListBox.Resources>
<DataTemplate DataType="{x:Type your_namespace:your_type}">
... your code ...
</DataTemplate>
<DataTemplate DataType="{x:Type system:String}">
... your code ...
</DataTemplate>
</ListBox.Resources>
</ListBox>
Code you posted is actually a new Template, but you've changed the Style. Please consider override some Template.
Best regards
I have the following resource in my window that declares how a certain kind of TabItem should look like.
<Window.Resources>
<StackPanel x:Key="TabSearchContents" x:Shared="False"
Orientation="Vertical">
<Border
BorderThickness="3"
BorderBrush="Purple">
<TextBlock
Text="SEARCH BOOKS"
FontFamily="Verdana"
FontSize="25"
Foreground="Blue"
HorizontalAlignment="Center" />
</Border>
<StackPanel
Height="30"
Orientation="Horizontal"
Margin="5">
<TextBox
x:Name="txtSearch"
Width="650"
FontFamily="Comic Sans MS"
Foreground="Chocolate" />
<Button
x:Name="btnSearch"
Width="100"
Content="Go!"
Click="BtnSearch_Click" />
</StackPanel>
<Grid x:Name="gridResults">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="450"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Column="0" VerticalScrollBarVisibility="Auto">
<ItemsControl x:Name="itmsSearch" ItemsSource="{Binding}" Padding="4"
ItemTemplate="{StaticResource SearchResultItemDT}">
</ItemsControl>
</ScrollViewer>
<StackPanel x:Name="stkpnlDetails">
</StackPanel>
</Grid>
</StackPanel>
</Window.Resources>
Then, in my code-behind, I dynamically create a tab and assign to the TabControl that is already present in my window.
void BtnNewTab_Click(object sender, RoutedEventArgs e)
{
TabItem tb = new TabItem();
tb.Content = this.Resources["TabSearchContents"];
tb.DataContext = _bridge.SearchBooksByTitle("e");
tb.Header = "Wuttp yo!";
Button btnGo = ((Button)tb.FindName("btnSearch"));
ItemsControl i = (ItemsControl)tb.FindName("itmsSearch");
btnGo.Resources.Add("ResultList", i);
daTabs.Items.Add(tb);
tb.Focus();
}
I want to access the btnSearch Button that is declared in my XAML resource.
As it is, this code throws an exception since btnGo turns out to be null (as well as i) since it can't find the expected control via FindName().
I read about the RegisterName() method, but it requires a reference to an instance of the required control... which I don't have.
I dont think you should define your button like this, try defining it in a style, creating a button and assigning the button that style, i think you will be able to get what you are going for this way.
myTheme.xaml
<ResourceDictionary
<Style x:Key="btnSearch" TargetType="{x:Type Button}">
<Setter Property="Width" Value="100"/>
<Setter Property="Content" Value="Go!"/>
<Setter Property="Click" Value="btn_Click"/>
</Style>
ResourceDictionary/>
myCode.cs
Button btnGo = new Button;
btnGo.Style = "{DynamicResource btnSearch}";
Hope this helps,
Eamonn
Let's say we have a grid XAML like below - eg. a generated string returned from a method.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width='*' />
<ColumnDefinition Width='*' />
</Grid.ColumnDefinitions>
<TextBlock Text='id' Grid.Column='0'/>
<Rectangle Fill='Black' Grid.Column='1' />
</Grid>
What I want to do is to create such a grid and added to a stackpanel at run time, codes similar as below.
XmlReader xr = XmlReader.Create(input: new StringReader(g.xaml));
var control = XamlReader.Load(xr) as Grid;
this.stackPanel.Children.Add(control);
The form I use is:
<Window x:Class='AllRibbonBrushes.MainWindow'
xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
Title='MainWindow' Height='223' Width='533'
Loaded='Window_Loaded'>
<ScrollViewer>
<StackPanel Name="stackPanel">
<!--The runtime grid need to be added here-->
</StackPanel>
</ScrollViewer>
</Window>
But I get the error Cannot create unknow type 'Grid'. I succeed doing this by adding a button/a textblock but failed to add a grid with nested controls.
If you know how to do so, please share. All helps are welcome and very much appreciated!
Add xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' to the first Grid element in the xaml you would like load. This declares the wpf namespace the default namespace in your xaml. XamlReader.Load can then find out what kind of control is.
<Grid xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>
<Grid.ColumnDefinitions>
<ColumnDefinition Width='*' />
<ColumnDefinition Width='*' />
</Grid.ColumnDefinitions>
<TextBlock Text='id' Grid.Column='0'/>
<Rectangle Fill='Black' Grid.Column='1' />
</Grid>
I have a number of UserControl classes:
DataTypeWholeNumber
DataTypeLine
DataTypeDate
DateTypeDuration
etc.
They all inherit from a plain C# class which inherits from UserControl which has no XAML attached to it. I had to do it this way since I was getting errors saying that XAML could not be inherited.
The problem is that the XAML for each of these UserControls is basically the same, so I would like to find some way to at least emulate XAML inheritance so that I don't have to repeat this code for 20 different classes:
<dataTypes:BaseDataType x:Class="TestDependencyProperty827.DataTypes.DataTypeLine"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dataTypes="clr-namespace:TestDependencyProperty827.DataTypes">
<StackPanel Margin="{Binding Margin}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding LabelWidth}"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="{Binding Label}" FontSize="14"/>
<TextBlock FontSize="14" Text=":"/>
</StackPanel>
<TextBox Grid.Column="1" FontSize="12" HorizontalAlignment="Left"
Text="{Binding Text}"
Width="{Binding Width}"/>
</Grid>
</StackPanel>
</dataTypes:BaseDataType>
Has anyone run into this problem and found a solution to it?
Use a Style that applies to the base class:
<Style TargetType="BaseClass">
<Setter Property="Control.Template">
<Control.Value>
<StackPanel Margin="{Binding Margin}">
<!-- Rest of code here -->
</Control.Value>
</Style>
Also, I question the need for UserControls for every one of the base types - why can't you just reuse the same UserControl everywhere?
A XAML class can't inherit from a XAML class, but a normal class can inherit from a XAML class - so if the XAML for all of those is the same put that XAML in BaseDataType and crate all the derived types as normal non-WPF c# classes.
If you need to derive other XAML user controls from BaseDataType than this is not possible but you can use styles, data templates or control templates to share the XAML between diffrent controls.