Add a disabled/ non-selectable separator in a bound ComboBox - visual-c++

I have a ComboBox and I want to add a separator which is disabled, non-selectable.
Standard functions such as add, edit, delete should be selectable under the separator.
The items containing an image and text should be displayed above the separator.
<ComboBox Name="cmbTest">
<!--These items should be loaded by code or ViewModel.-->
<ComboBoxItem >Item1</ComboBoxItem>
<ComboBoxItem >Item2</ComboBoxItem>
<ComboBoxItem >Item3</ComboBoxItem>
<!--Separator which is disabled.-->
<ComboBoxItem IsEnabled="False" >
<NavigationViewItemSeparator BorderThickness="1"></NavigationViewItemSeparator>
</ComboBoxItem>
<!--Menu below the separator.-->
<ComboBoxItem x:Name="cmbiNewApplication">Neu</ComboBoxItem>
<ComboBoxItem x:Name="cmbiEdit">Bearbeiten</ComboBoxItem>
<ComboBoxItem x:Name="cmbiDelete">Löschen</ComboBoxItem>
<ComboBoxItem x:Name="cmbiImportApplication">Import</ComboBoxItem>
<ComboBoxItem x:Name="cmbiExportApplication" >Export</ComboBoxItem>
</ComboBox>
Currently, my ComboBox is tied to a ViewModel and I've created a TemplateSelector on advice. Unfortunately, the ComboBoxItem in the template doesn't seem to be the generated ComboBoxItem itself, so the IsEnabled property has no effect.
<ComboBox x:Name="cmbApplication"
CornerRadius="3"
Width="300"
ItemsSource="{x:Bind AppProcessMainViewModel.AppProcesses}"
Tapped="cmbApplication_Tapped" >
<ComboBox.ItemTemplateSelector>
<local:MenuDataTemplateSelector>
<local:MenuDataTemplateSelector.DefaultTemplate>
<DataTemplate x:DataType="local:AppProcess" >
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal" Opacity="{x:Bind BoolToOpacity(Activated), Mode=OneWay}">
<TextBlock Text="{x:Bind Description, Mode=OneWay}"></TextBlock>
</StackPanel>
</StackPanel>
</DataTemplate>
</local:MenuDataTemplateSelector.DefaultTemplate>
<local:MenuDataTemplateSelector.MenuTemplate>
<DataTemplate x:DataType="local:AppProcess">
<ComboBoxItem IsEnabled="False" Height="22" >
<NavigationViewItemSeparator BorderThickness="1"></NavigationViewItemSeparator>
</ComboBoxItem>
</DataTemplate>
</local:MenuDataTemplateSelector.MenuTemplate>
</local:MenuDataTemplateSelector>
</ComboBox.ItemTemplateSelector>
</ComboBox>
My consideration was that I set the IsEnabled property of the item in the Tapped event of the combo box.
Unfortunately, I really can't figure out how to get the property of the ComboBoxItem by index.
How can I set the property?
Is this really the best approach (TemplateSelector and setting the property in the Tapped event)?
I've already read a lot about this and unfortunately there seems to be a lot missing in WinUI 3 in contrast to UWP/WPF that make things much easier.
I'm trying to get the item via the index and cast it, but there seems to be another problem, maybe because of the ViewModel?
Something like...
//Error
auto cb = cmbApplication().Items().GetAt(1).as<winrt::Microsoft::UI::Xaml::Controls::ComboBoxItem>();

I came across this site of the MS documentation (Find DataTemplate Generated Elements) and just tried it out, which works wonderfully... happy new year!
auto item = cmbApplication().ItemContainerGenerator().ContainerFromItem(cmbApplication().Items().GetAt(3));
item.as< winrt::Microsoft::UI::Xaml::Controls::ComboBoxItem>().IsEnabled(false);

Related

How to use sort="auto" on A object?

I have a listheader element with sort="auto" set, but when I click the column, the list doesn't sort. The arrows appear and reverse direction, but the list order doesn't change.
The Components appended to the list are org.zkoss.zul.A objects, which appears to be the reason sorting does not work.
Is there a workaround to get sorting to work for a Listbox whose list items are A objects?
my zul:
<listbox id="myList" checkmark="true" multiple="true">
<listhead>
<listheader id='select' label="" width="30px" align="left"/>
<listheader label="myLabel" width="75px" sort="auto"/>
</listhead>
</listbox>
groovy:
Listitem li = new Listitem(value: "myId")
li.appendChild(new Listcell())
Listcell listcell = new Listcell()
Long theId = "12345"
A link = new A(label: theId.toString(), style: "color:blue;")
listcell.appendChild(invoiceLink)
li.appendChild(listcell)
I'am using MVVM approach and this is how I sort my listbox
<listbox>
<listhead>
<listheader label="Hopper" width="60px" sort="auto(hopperCode)" />
<listheader label="Stop Time" width="80px" sort="auto(startTime)" />
</listhead>
<template name="model">
<listitem>
<listcell label="#load(each.hopperCode)" />
<listcell label="#load(each.startTime)" />
</listitem>
</template>
</listbox>
According to this paragraph in the documentation, sort auto sorts by the label of the listcell. You are not using Listcell.setLabel(), but append an A component to it. Since the listcells' labels are all the same (i.e. ""), sorting doesn't do anything.
Try setting custom comparators. For this purpose I advise using a model instead of creating the listitems yourself.

how to take value of tapped column/bar of winrt xaml column series chart using c#

how to take value of tapped column/bar of winrt xaml column series chart.
i want to open other chart using the value of each bar..
my code is:
<Charting:Chart x:Name="chart" Title="My Performance" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,0,0,0" Width="895" Height="548" Foreground="Black" FontSize="10" >
<Charting:ColumnSeries x:Name="mychart" Padding="10" BorderThickness="5" BorderBrush="#FF233083" Background="Yellow" IndependentValuePath="TestCode" DependentValuePath="Percentage" IsSelectionEnabled="True" Margin="0,0,0,4" Tapped="mychart_Tapped" >
i didn't get values from selecteditem thanks........

Header template and title

Let say that we have the above xaml in wp7 platform:
<controls:Panorama x:Name="MainPanorama">
<controls:PanoramaItem x:Name="Panorama1" TabIndex="1">
<controls:PanoramaItem.Header>
<StackPanel Orientation="Vertical" Margin="12,70,0,-30">
<TextBlock x:Name="Header1" Text="Downloader" FontSize="50" Margin="-5,-70,0,0" />
</StackPanel>
</controls:PanoramaItem.Header>
///////////////////////////////
other xaml code like grids and other
</controls:PanoramaItem>
///////////////////////////////
other xaml code like PanoramaItems
</controls:Panorama>
How can i get the TextBlock.Text (string) of Header1, notice that i want something dynamically as i have many PanoramaItems and i want to get header of every PanoramaItem dynamically like an array of MainPanorama.
I have tried this:
PanoramaItem gen_panorama = MainPanorama.SelectedItem as PanoramaItem;
gen_panorama_head = Convert.ToString(gen_panorama.Header);
but there is no Header as the header is in template of every PanoramaItem, how can i get this?
I found the solution with 'Binding' header data template!
<controls:Panorama x:Name="MainPanorama">
<controls:Panorama.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Margin="12,70,0,-30">
TextBlock Text="{Binding}" FontSize="50" Margin="-12,-70,0,0" HorizontalAlignment="Left" Foreground="Black" />
</StackPanel>
</DataTemplate>
</controls:Panorama.HeaderTemplate>
<controls:PanoramaItem Header="Here any we want" x:Name="Panorama1" TabIndex="1">
</controls:PanoramaItem>
</controls:Panorama>

WPF - Border with a OpacityMask/VisualBrush: Memory Leaks

A brief explanation about my app:
the application in which I'm working on is such a greeting cards designer. Imagine something in which there is a background image, and an indefinite number of "layers" (in particular, pictures) that stay over the background and can be moved, resized, moved front and back, etc...
It is also possibile to apply particular shapes to these layers, like a star, an ellipse, .. and after the card is made, it's possibile to save is to jpeg file.
The problem
Everything works correctly, but I detected that when a shape is applied to a layer, a memory leak is generated.
Here is the code of the UserControl of each layer:
<UserControl>
.....
<Grid x:Name="_myGrid" >
<Border x:Name="im_the_problem" BorderThickness="0" OpacityMask="{Binding Path=MyMask.Data, Converter={StaticResource MaskConverter}}">
<!-- My Image... -->
</Border>
</Grid>
</UserControl>
where MaskConverter code is the following:
public class MaskConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
String maskData = value as String;
if (maskData == null)
return null;
if (maskData == "")
return null;
VisualBrush vb = new VisualBrush();
vb.Visual = XamlReader.Parse(maskData) as Visual;
return vb;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
The Parameter "MyMask.Data" is a XAML Path (that is the shape that I'm applying) that I dinamically load from a textfile that contains different shapes.
So, the principle is that if I have the border named *im_the_problem*, the memory is NOT released. If I comment *im_the_problem* (so I'll just have rectangular layers/pictures without shapes) everything work like a charm, without memory leaks.
The problem should be in the OpacityMask + VisualBrush.
Am I doing something wrong?
Or is there a known problem? Is there a way to do the same (apply a shape to a picture..) in a different manner?
Thanks.
You might be able to try binding the MyMask.Data to an actual Path.Data, and setting the Path.Fill to an ImageBrush created from the image?
You need to freeze your VisualBrush ;)
I had this problem in a DataGrid's column template where I was using a <Canvas><Path /></Canvas> (as a static-resource) into a VisualBrush (also a static-resource) and using that as the OpacityMask for a Rectangle. Whenever the DataGrid was reloaded the Rectangle wouldn't release VisualBrush references to the OpacityMask, I used a memory-profiler tool to reveal that all the VisualBrush objects were using the bulk of memory.
I don't understand why or how this happened - but I'm glad I'm not alone (even if I had the same problem some 6.5 years later...).
My XAML was something like this:
<DataGrid.Resources>
<Canvas x:Key="icon" ...>
<Path ... />
</Canvas>
<VisualBrush x:Key="iconBrush" Stretch="Uniform" Visual="{StaticResource icon}" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Rectangle
Fill="{Binding Foreground, ElementName=myDataGrid}"
Width="14"
Height="14"
Margin="4"
Visibility="{Binding IconVisibility}"
OpacityMask="{StaticResource iconBrush}"
/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...
</DataGrid.Columns>
I read that setting IsFrozen = true (done using this technique: https://www.codeproject.com/Tips/72221/Freeze-brushes-directly-in-the-XAML-to-improve-you ) would help memory issues with Brushes, however this seemingly had no effect at all. Weird.
I thought I'd experiment and I reasoned that if the issue was leaking the VisualBrush then I wondered if having it as a StaticResource was messing with object-references, so I changed it to an "owned" object, like so:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Rectangle
Fill="{Binding Foreground, ElementName=myDataGrid}"
Width="14"
Height="14"
Margin="4"
Visibility="{Binding IconVisibility}"
>
<VisualBrush Stretch="Uniform" Visual="{StaticResource iconBrush}" />
</Rectangle>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
This fixed the issue! And I still don't know why - I wonder if it's a bug in WPF?
On a related note, I came to realise that using a VisualBrush was overkill as I'm rendering just a simple Path - VisualBrush is expensive because it renders an entire WPF view - I also learned from other documentation that Path itself isn't necessary for rendering simple shapes because itself is a complete UIElement and FrameworkElement - which are "heavier" types.
I changed my code to store the path in a PathGeometry value inside a GeometryDrawing static-resource which is loaded into a DrawingBrush:
<GeometryDrawing x:Key="iconDrawing" Brush="Black" Geometry="..." />
<Rectangle
Fill="{Binding Foreground, ElementName=myDataGrid}"
Width="14"
Height="14"
Margin="4"
Visibility="{Binding IconVisibility}"
OpacityMask="{StaticResource iconBrush}"
>
<DrawingBrush Stretch="Uniform" Drawing="{StaticResource iconDrawing}" />
</Rectangle>
Doing this also made a dent in memory usage, and hopefully, performance.
In your project I see you're not using the path information as a resource, but the same technique applies: load your path into a PathGeometry (or rather, StreamGeometry object, which is even faster and is meant for immutable geometry) and set that as the Drawing for a DrawingBrush.

Adding an item to ItemControl which is not from binding Items Source

I am working on generating a list of check boxes with the first check box to be "SelectAll". SelectAll checkbox will check or uncheck all the check box in the list. However my check list is binding to a data source. Right now I want to put all check box including selectAll check box in the same wrappanel so that they can be wrapped together at the end of the panel.
<ContentControl Name="FilterContent">
<WrapPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<CheckBox Name="SelectedAll" MinWidth="100" Margin="2"
VerticalAlignment="Center" HorizontalAlignment="Left"
IsChecked="{Binding IsSelectAll, Mode=TwoWay}"
Content="{Binding Path=SelectAllText}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cmd:EventToCommand Command="{Binding Path=OnClickCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
<ItemsControl ItemsSource="{Binding StandardItems}"
Margin="2,5,2,-1"
BorderBrush="{x:Null}"
Background="Transparent"
Grid.ColumnSpan="2"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ScrollViewer.HorizontalScrollBarVisibility="Hidden">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Name="ItemsPanel" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Name="ItemCheckBox"
MinWidth="100" Margin="2"
VerticalAlignment="Center" HorizontalAlignment="Left"
IsChecked="{Binding Path=IsChecked, Mode=TwoWay}"
Content="{Binding Path=Label}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</WrapPanel>
</ContentControl>
This piece of code does not allow me to do that, the result UI only have the items inside item control wrapped in the second line but not consider all check box in the same wrappanel. I need help on adding "SelectAll" check box to the wrappanel that is used by itemscontrol.
Thank you!
When loading the control I would add an empty StandardItem in the StandardItems list which will mean "select all". When I process the checkbox click event, I check if the item is an empty item and I use this as a call to "select all"

Resources