WPF multibinding visibility of a grid template - c#

I have a list view which each listview which contain several columns of data. this list view contain 2 grids, 1 grid which is the header.
and a secound grid which show all the relavent data.per the items
what I am trying to perform is to hide some of the data per properites the value of some fields in the data.
how can I do that? I tried multiyBinding by I am getting an error:
"'Binding' cannot be set on the 'Path' property of type 'Binding'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject."
would be happy for a code example
here is the code I have written
<ListView x:Name="LVGuiCoreBus" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" MouseDown="LVGui_MouseDown" Grid.Row="1" VirtualizingPanel.IsContainerVirtualizable="True" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.IsVirtualizingWhenGrouping="True" SelectionChanged="LVGuiCoreBus_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<VirtualizingStackPanel >
<Grid VirtualizingPanel.VirtualizationMode="Recycling">
<Grid.Visibility>
<MultiBinding>
<Binding Path="{Binding Source, Converter={StaticResource VisiblieGroupFilterBySourcecs},UpdateSourceTrigger=PropertyChanged}"></Binding>
<Binding Path="{Binding Destination, Converter={StaticResource VisiblieGroupFilterBySourcecs},UpdateSourceTrigger=PropertyChanged}"></Binding>
</MultiBinding>
</Grid.Visibility>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="70"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding DateNTimeStr}" Foreground="Green" Grid.Column="0" />
<TextBlock Text="{Binding Source}" Foreground="{Binding Source,Converter={StaticResource CoreBusPanelModuleColorConverter},UpdateSourceTrigger=PropertyChanged}" Grid.Column="2" Background="{ Binding Source, Converter={StaticResource BackGroundFilterConverterBySource}}" />
<TextBlock Text="{Binding Destination}" Foreground="{Binding Destination,Converter={StaticResource CoreBusPanelModuleColorConverter},UpdateSourceTrigger=PropertyChanged}" Grid.Column="4" Background="{ Binding Destination, Converter={StaticResource BackGroundFilterConvertorByDestantation}}" />
<TextBlock Text="{Binding Module}" Grid.Column="6" HorizontalAlignment="Center" Background="{ Binding Module, Converter={StaticResource BackGroundFilterByModule},UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="{Binding Controll}" Grid.Column="8" Background="{ Binding Controll, Converter={StaticResource BackGRoundFilterByControll},UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="{Binding Command}" Grid.Column="10" HorizontalAlignment="Center" Background="{ Binding Command, Converter={StaticResource BackGroundFilterByCommand},UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="{Binding HSCommand}" Grid.Column="12" HorizontalAlignment="Center" Background="{ Binding HSCommand, Converter={StaticResource BackGroundFilterByHsCommand},UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="{Binding Data_Str}" Grid.Column="14" />
</Grid>
</VirtualizingStackPanel>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ContextMenu>
<ContextMenu x:Name="CMMenuCopy">
<MenuItem x:Name="MCICopyLine" Header="Copy Line" Click="MCICopyLine_Click" ></MenuItem>
<MenuItem x:Name="MCICopyText" Header="Copy Only Data Array" Click="MCICopyText_Click" ></MenuItem>
<MenuItem x:Name="MCIClear" Header="Clear" Click="MCIClear_Click"></MenuItem>
</ContextMenu>
</ListView.ContextMenu>
</ListView>

You should change your code following these two steps:
Change your Binding markup extension to Binding object.
Add an IMultiValueConverter to your `MultiBinding.
As a result, you can change your MultiBinding usage like this:
<MultiBinding Converter="{StaticResource YouShouldWriteANewMultiBindingConverterHere}">
<Binding Path="Source" Converter="{StaticResource VisiblieGroupFilterBySourcecs}" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="Destination" Converter="{StaticResource VisiblieGroupFilterBySourcecs}" UpdateSourceTrigger="PropertyChanged" />
</MultiBinding>
First, the {Binding xxx, Converter=xxx} is used as a MarkupExtension can only be used on a dependency property. But when you use Binding in a MultiBinding, you're treating it as a Binding object instead of a MarkupExtension. so you should set the Binding properties just like a normal XAML object.
Second, a MultiBinding needs an IMultiValueConverter or a StringFormat property set.
public class YouShouldWriteANewMultiBindingConverterHere : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
=> throw new NotImplementedException();
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
=> throw new NotImplementedException();
}
You can learn more about MarkupExtension, MultiBinding, IMultiValueConverter by reading these:
Markup Extensions and WPF XAML | Microsoft Docs
Data Binding Overview | Microsoft Docs
MultiBinding Class (System.Windows.Data) | Microsoft Docs
IMultiValueConverter Interface (System.Windows.Data) | Microsoft Docs

Related

How to avoid repeating blocks of XAML in a menu

I have to create a menu. It has 10 entries and they differ by one parameter.
Entry 1:
<MenuItem Visibility="{Binding MenuSelected.Type, Converter={StaticResource TypeToVisibilityConverter}, ConverterParameter='PAZ', Mode=OneWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding CmdContextMenu}" CommandParameter="PAZ" />
</i:EventTrigger>
</i:Interaction.Triggers>
<MenuItem.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="Segoe MDL2 Assets"
Foreground="{Binding MenuSelected.Type, Converter={StaticResource TypeToColorConverter}, ConverterParameter='PAZ', Mode=OneWay}"
Text="{Binding MenuSelected.Type, Converter={StaticResource TypeToIconConverter}, ConverterParameter='PAZ', Mode=OneWay}" />
<TextBlock
Grid.Column="1"
Margin="{StaticResource XSmallLeftMargin}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="PAZ" />
</Grid>
</MenuItem.Header>
</MenuItem>
Entry 2:
<MenuItem Visibility="{Binding MenuSelected.Type, Converter={StaticResource TypeToVisibilityConverter}, ConverterParameter='APP', Mode=OneWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding CmdContextMenu}" CommandParameter="APP" />
</i:EventTrigger>
</i:Interaction.Triggers>
<MenuItem.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="Segoe MDL2 Assets"
Foreground="{Binding MenuSelected.Type, Converter={StaticResource TypeToColorConverter}, ConverterParameter='APP', Mode=OneWay}"
Text="{Binding MenuSelected.Type, Converter={StaticResource TypeToIconConverter}, ConverterParameter='APP', Mode=OneWay}" />
<TextBlock
Grid.Column="1"
Margin="{StaticResource XSmallLeftMargin}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="APP" />
</Grid>
</MenuItem.Header>
</MenuItem>
As you can see, the only difference is between PAZ and APP in different points... and same goes on for all the others.
Is there a way I can avoid to repeat it 10 times just changing the 3 letters?
I do not want to use code-behind to create the menu dynamically... but to process it from XAML.
From your question I assume that CmdContextMenu and MenuSelected are properties on your main view model and not in a separate menu item type. If this is different, you have to adapt the code accordingly.
In order to remove the redundant code, create a collection for your menu items in your view model.
public class MyMainViewModel : INotifyPropertyChanged
{
public IEnumerable<string> MyTypes { get; } = new List<string>
{
"PAZ",
"APP"
};
// ...other properties and methods (like "CmdContextMenu" and "MenuSelected" I Assume).
}
Next, you have to change the value converters, because the ConverterParameter is not a dependency property and cannot be bound. Instead, you can use IMultiValueConverters that can bind multiple values. Adapt all of your converters to implement IMultiValueConverter. Here is an example of how a converter could look like. Of course, it depends on your implementation. In essence, use the values array to access bound values.
public class TypeToVisibilityConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values[0].Equals(values[1]) ? Visibility.Visible : Visibility.Collapsed;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Next, create a data template for the header of your menu items. As you can see, the bindings are replaced with MultiBindings that use an IMultiValueConverter as Converter.
The first binding in each block is a RelativeSource binding to access the data context of the parent Menu, because I assume that the MenuSelected property is defined on your main view model. The other empty bindings will bind to the data context of the current menu item, which is an item from the MyTypes collection.
<DataTemplate x:Key="MyMenuItemHeaderTemplate" DataType="{x:Type system:String}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="Segoe MDL2 Assets">
<TextBlock.Foreground>
<MultiBinding Converter="{StaticResource TypeToColorConverter}">
<Binding Path="DataContext.MenuSelected.Type" RelativeSource="{RelativeSource AncestorType={x:Type Menu}}" Mode="OneWay"/>
<Binding/>
</MultiBinding>
</TextBlock.Foreground>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource TypeToIconConverter}">
<Binding Path="DataContext.MenuSelected.Type" RelativeSource="{RelativeSource AncestorType={x:Type Menu}}" Mode="OneWay"/>
<Binding/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<TextBlock Grid.Column="1"
Margin="{StaticResource XSmallLeftMargin}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{Binding}"/>
</Grid>
</DataTemplate>
Create a new header item style that uses this data template. The Visibility also uses a multi-value converter as above. Instead of using an event trigger, you can simply assign the command to the menu item directly and pass a CommandParameter, which is bound to the data context of the current menu item.
<Style x:Key="MyMenuItemStyle" TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
<Setter Property="HeaderTemplate" Value="{StaticResource MyMenuItemHeaderTemplate}"/>
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource TypeToVisibilityConverter}">
<Binding Path="DataContext.MenuSelected.Type" RelativeSource="{RelativeSource AncestorType={x:Type Menu}}" Mode="OneWay"/>
<Binding/>
</MultiBinding>
</Setter.Value>
</Setter>
<Setter Property="Command" Value="{Binding DataContext.CmdContextMenu, RelativeSource={RelativeSource AncestorType={x:Type Menu}}}"/>
<Setter Property="CommandParameter" Value="{Binding}"/>
</Style>
Finally, create a Menu and bind the MyTypes collection, as well as the style.
<Menu ItemsSource="{Binding MyTypes}" ItemContainerStyle="{StaticResource MyMenuItemStyle}"/>
ConverParameter property is not a DependencyProperty - so it cannot be Bound to.
You can use a MultiValue converter instead.
Instead of creating 10 menu items in xaml manually, you should be able to bind an ItemsCollection and define a DataTemplate for MenuItem

C# WPF binding to method with ObjectDataProvider

I have a strange behaviour using ObjectDataProvider. I need to bind a TextBlock with ToString method but, when I enter in method my properties are wrong.
This is my simple ObjectDataProvider:
<Window.Resources>
<ObjectDataProvider x:Key="ToString" MethodName="ToString" ObjectType="{x:Type entities:Season}" />
</Window.Resources>
And this is my ListView:
<ListView Grid.Row="2" Name="lvSeasons" HorizontalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Source={StaticResource ToString}}" VerticalAlignment="Center" />
<Button Grid.Column="1" VerticalAlignment="Center" Background="Transparent" BorderBrush="Transparent" Click="btDeleteSeason_Click">
<TextBlock FontFamily="{StaticResource FontAwesome}" Text="" FontSize="20" Foreground="Red" HorizontalAlignment="Center" />
</Button>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
My method simply concat two properties:
public override string ToString()
{
return StartYear + "/" + EndYear;
}
In debug I can see that start and end year are always 0. If I bind my TextBlock using {Binding StartYear} it's correct and value is 2019.
Where can the problem be?
You do not need an ObjectDataProvider. Just write
<TextBlock Text="{Binding}" ... />
WPF will call the ToString method by default.
You do not even need to override ToString when you use a MultiBinding with an appropriate StringFormat:
<TextBlock ...>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}/{1}">
<Binding Path="StartYear "/>
<Binding Path="EndYear "/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>

How to auto height set to itemscontrol in wpf?

I have using the itemscontrol in WPF, I have given the dictionary collection as itemsource for itemscontrol. In this dictionary collection, will be used key and observablecollection. Different items will be in observablecollection of each dictionary items. so, when i'm given an itemsource it will be taken same height.
see the code:
<ItemsControl
Grid.Row="1"
Height="Auto"
ItemsSource="{Binding Values}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
IsItemsHost="True"
Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<GroupBox
MinWidth="303"
Margin="5,0,0,0">
<ItemsControl Margin="20,5,0,5">
<ItemsControl.Resources>
<CollectionViewSource x:Key="Collection" Source="{Binding Value}" />
<DataTemplate DataType="{x:Type Model:Sensor}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label
Grid.Column="1"
Content="{Binding Name}"
FontFamily="SegoeUI-Semibold"
FontSize="12"
FontWeight="SemiBold" />
<Label
Grid.Column="2"
HorizontalContentAlignment="Center"
Content="{Binding Value}"
FontFamily="SegoeUI"
FontSize="12" />
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type Model:DigitalInput}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label
Grid.Column="1"
Content="{Binding Name}"
FontFamily="SegoeUI-Semibold"
FontSize="12"
FontWeight="SemiBold" />
<Label
Grid.Column="2"
HorizontalContentAlignment="Center"
Content="{Binding InputState}"
FontFamily="SegoeUI"
FontSize="12" />
</Grid>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource Collection}}" />
</CompositeCollection>
</ItemsControl.ItemsSource>
</ItemsControl>
</GroupBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
see the class code:
private Dictionary<string, ObservableCollection<IValue>> values;
public Dictionary<string, ObservableCollection<IValue>> Values
{
get { return values; }
set { values = value; }
}
Current output:
Expected output:
I need to group the items as an expected output, so could you please provide any solution to achieve that?
This is how WrapPanel works. If you set Horizontal all items in row will have same height and it wraps elements to the next row.
You can try specifying Orientation="Vertical" for your WrapPanel, but not quite sure if it suits you. In this case all elements in column will have same width.
Otherwise you don't need either WrapPanel or UniformGrid, you need different panel which is called StaggeredPanel. Source code for uwp can be easily used in WPF, I just checked it.
Only had to rewrite one line which is not a big deal with the following answer: RegisterPropertyChangedCallback(Panel.HorizontalAlignmentProperty, OnHorizontalAlignmentChanged);
An explanation for similar control can be found on codeproject (Called VariableSizedWrapGrid). But I checked it and it has errors somewhere.
On ios it's called mosaic view or StaggeredLayoutManager for RecyclerView on Android.
Instead of WrapPanel, try a UniformGrid:
<UniformGrid Columns="1" IsItemsHost="True" />
Also, I'm not sure about the Height="Auto" setting. Remove it. The setting belongs to the RowDefinition of the grid.

DataTemplate localization using WPFLocalizationExtension

I'm using WPFLocalizationExtension to localize a C#/ .Net4.5 application but I didn't manage to localize DropDown Menus with custom DataTemplate because I can't use the DisplayMemberPath. For ordinary dropdown localization works like this:
<telerik:RadComboBox ItemsSource="{Binding GlassColors}"
SelectedValue="{Binding Ampule.ID_GlassColor, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
SelectedValuePath="ID_GlassColor"
DisplayMemberPath="{lang:Loc dmp_GlassColor}"/>
The ComboBox example above is linked to a database table containing to language. The displayed language is changed by the localized DisplayMemberPath. This approach is very easy and I can recommend it to everyone else. How ever it doesn't work for comboboxes using a custom DataTemplate. See example below:
<telerik:RadComboBox ItemsSource="{Binding PackagingTypesFilter}"
SelectedValue="{Binding SelectedPackagingTypeFilter}"
SelectedValuePath="ID_PackagingType">
<telerik:RadComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type model:Tbl_PackagingMaster_ID_PackagingType}">
<Grid VerticalAlignment="Center" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding TypeIcon, Converter={StaticResource StringToUriConverter}}" VerticalAlignment="Top" Grid.Column="0" Height="14" Margin="2" />
<TextBlock Text="{Binding PackagingTypeDescription}" Style="{StaticResource TextBlockMediumSmallBlackStyle}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</telerik:RadComboBox.ItemTemplate>
</telerik:RadComboBox>
The ItemSource is a Collection where PackagingTypeDescription contains the English and PackagingTypeDescriptionGerman contains the German description.
How can I localize the code sample above?
I solved this using a TemplateSelector.
Here is the TemplateSelector class:
using System.Windows;
using System.Windows.Controls;
namespace Common.TemplateSelector
{
public class LanguageTemplateSelector : DataTemplateSelector
{
public DataTemplate TemplateEnglish { get; set; }
public DataTemplate TemplateGerman { get; set; }
public const string LanguageIdentifier = "de";
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
return Configuration.Configuration.Language == LanguageIdentifier ? this.TemplateGerman : this.TemplateEnglish;
}
}
}
And here the template definition and the definition of the TemplateSelector defined in the <UserControl.Resources></UserControl.Resources> area:
<DataTemplate DataType="{x:Type model:Tbl_PackagingMaster_ID_PackagingType}" x:Key="PackagingTypeEnglish">
<Grid VerticalAlignment="Center" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding TypeIcon, Converter={StaticResource StringToUriConverter}}" VerticalAlignment="Top" Grid.Column="0" Height="14" Margin="2" />
<TextBlock Text="{Binding PackagingTypeDescription}" Style="{StaticResource TextBlockMediumSmallBlackStyle}" Grid.Column="1"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type model:Tbl_PackagingMaster_ID_PackagingType}" x:Key="PackagingTypeGerman">
<Grid VerticalAlignment="Center" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding TypeIcon, Converter={StaticResource StringToUriConverter}}" VerticalAlignment="Top" Grid.Column="0" Height="14" Margin="2" />
<TextBlock Text="{Binding PackagingTypeDescriptionGerman}" Style="{StaticResource TextBlockMediumSmallBlackStyle}" Grid.Column="1"/>
</Grid>
</DataTemplate>
<templateSelector:LanguageTemplateSelector x:Key="PackagingTypeLanguageSelector"
TemplateEnglish="{StaticResource PackagingTypeEnglish}"
TemplateGerman="{StaticResource PackagingTypeGerman}" />
This is how I use it for the ComboBox:
<telerik:RadComboBox ItemsSource="{Binding PackagingTypesFilter}"
SelectedValue="{Binding SelectedPackagingTypeFilter}"
SelectedValuePath="ID_PackagingType"
ItemTemplateSelector="{StaticResource PackagingTypeLanguageSelector}" />
However, I'm still looking for a more elegant way to solve this.

How to freeze a column in Grid and make it always shown in client area of a WPF user control

I searched in stackoverflow, and there is a property FrozenColumnCount for DataGrid, but Grid control doesn't have that property.
We have a Grid with 2 columns. Now, we need to freeze the last column in a grid, and make it always shown in the client area of the user control. otherwise, if the data (such as text) in first column is too long, customer has to use mouse to drag the horizon scroll bar to show the 2nd column.
We want customer can always see the data in 2nd column, so I wonder if we could freeze the specified column.
Update 1: I paste my code for the tree view control.
<HierarchicalDataTemplate x:Uid="HierarchicalDataTemplate_1" x:Key="MyPaletteMyTestTreeCell"
ItemsSource="{Binding Converter={StaticResource MyTestDataAccessor}}"
ItemTemplateSelector="{StaticResource MyTestDataAccessor}">
<ContentControl x:Uid="ContentControl_1" MouseDoubleClick="Item_MouseDoubleClick" ContextMenu="{StaticResource TreeListViewItemContextMenu}" MouseRightButtonDown="MRClick" Focusable="False">
<Grid x:Uid="Grid_2" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Uid="ColumnDefinition_3" />
<ColumnDefinition x:Uid="ColumnDefinition_2" Width="Auto" />
</Grid.ColumnDefinitions>
<Grid x:Uid="Grid_3" Grid.Column="0">
<StackPanel x:Uid="StackPanel_3" HorizontalAlignment="Left" Orientation="Horizontal">
<pc:ThemedImage x:Uid="Image_4"
LightSource="{Binding CategoryId, Converter={StaticResource LightMyTestIconConverter}, Mode=OneWay}"
DarkSource="{Binding CategoryId, Converter={StaticResource DarkMyTestIconConverter}, Mode=OneWay}"
Width="16" Height="16"
Margin="0,1,0,1"
VerticalAlignment="Center"/>
<TextBlock x:Uid="TextBlock_13" Text="{Binding Name}" VerticalAlignment="Center" Margin="3,0,0,1" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap"/>
</StackPanel>
</Grid>
<Grid x:Uid="Grid_4" Grid.Column="1">
<CheckBox x:Uid="CheckBox_3" HorizontalAlignment="Right" Click="CheckBox_Click" Grid.Column="1" Style="{StaticResource MyPaletteMyTestVisibilityStyle}" ToolTip="On/Off" Focusable="False">
<CheckBox.IsChecked>
<Binding x:Uid="Binding_1" Converter="{StaticResource MyTestDataAccessor}" Path="Visibility" Mode="OneWay">
<Binding.ConverterParameter>
<FrameworkElement x:Uid="FrameworkElement_1" DataContext="{TemplateBinding DataContext}" Tag="Visibility"/>
</Binding.ConverterParameter>
</Binding>
</CheckBox.IsChecked>
<CheckBox.IsEnabled>
<Binding x:Uid="Binding_2" Converter="{StaticResource MyTestDataAccessor}" Path="Visibility" Mode="OneWay">
<Binding.ConverterParameter>
<FrameworkElement x:Uid="FrameworkElement_2" DataContext="{TemplateBinding DataContext}" Tag="Enabled"/>
</Binding.ConverterParameter>
</Binding>
</CheckBox.IsEnabled>
</CheckBox>
</Grid>
</Grid>
</ContentControl>
</HierarchicalDataTemplate>
SOLUTION:
I found the cause. I have specified a horizon scroll bar for it.
So, when I removed it and use the code above, it can work as expected.
thanks a lot.
Clearly, you're not thinking about this correctly. You just need to put the column that you want to 'freeze' into a column of an outer Grid. Try something this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<!-- Your other controls -->
</Grid>
<Grid Grid.Column="1" Name="FrozenColumn">
<!-- Your frozen controls -->
</Grid>
</Grid>

Categories