Determine if ListBoxItem is currently on screen - c#

I have a ListBox using a Panel as its ItemsPanel
What I would like to do is load the bytes for an image into the bound property in the view model for each ListBoxItem that is currently on screen, and unload the bytes when they are scrolled off screen.
I have tried Panel.OnVisualChildrenChanged. This tells me when items are added or removed to the panel, but doesn't seem to help my specific case.
I have tried
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="RequestBringIntoView" Handler="EventSetter_OnHandler" />
</Style>
That event never seems to fire. edit: fires when item is selected
I have also gotten a reference to the ListBox ScrollViewer to look at the VerticalOffset and Viewport.Height/Width but I don't see how that information helps me.

Related

How to reference the default style ControlTemplate for ListViewItem in WPF?

In WPF, if I apply a GridView to a ListView, then it will automatically change the Template property of the ListViewItem to a ControlTemplate that uses a GridViewRowPresenter instead of a ContentPresenter. This is usually what you want.
As it happens, though, I have a case where I want to keep the original ContentPresenter, so that it will render the ItemTemplate of the ListView.
(For the curious: I'm doing a parent-child thing where the columns are actually for the child elements, so while I do still have a GridViewRowPresenter, it's inside another list control inside the ItemTemplate of the ListView.)
I can do this by setting an ItemContainerStyle on the ListView, and setting the Template property in that to a custom ControlTemplate, since this will override the style setter that the GridView applies.
However this gets really wordy (especially to keep the selection colours) and it breaks the natural theme support, unless I make duplicate copies of the template for each theme, which is definitely silly.
What I really want to do is to write this:
<Setter Property="Template"
Value="{StaticResource {FindDefaultControlTemplate ListViewItem}}" />
Where the latter bypasses the ControlTemplate set by the GridView and obtains the ControlTemplate that a normal ListViewItem would have used.
Alternatively, if there's some way to tell a GridView to not alter the ListViewItem style at all, that would also work for my scenario.
This has to work inside XAML.
It appears that the magic incantation is to set this style:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem"
BasedOn="{StaticResource {x:Type ListBoxItem}}" />
</ListView.ItemContainerStyle>
Apparently ListViewItem itself doesn't have a default style, but ListBoxItem does.
And this does override whatever GridView does and makes it use a plain ContentPresenter again.

Vertically Centering MenuItem text in a Fluent Ribbon with C# WPF

I'm working with Fluent.Ribbon, and I am desperately trying to vertically center the text of second level menu items. I actually wouldn't mind making second level have the same style as first level items if that would be easier.
From digging through the source code, I think I've found that the separate style is defined by the ControlTemplate ApplicationMenuSecondLevelItemTemplate. However, since I'm working on learning WPF, I'm not sure how to override that with styles.
I've tried simpler solutions, like this one which just makes the text disappear.
I've also tried all of the option in this post. However, none of those work either, and when I fix the last one to be the following to get rid of errors, the application just crashes.
<Style x:Key="CenteredTextMenuItem" TargetType="{x:Type MenuItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBox Text="{Binding}" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center" FontSize="16" FontWeight="Bold"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Height" Value="30"/>
<Setter Property="Width" Value="188"/>
</Style>
How can I center a second level MenuItem's text with the Fluent.Ribbon control?
Thanks.
Edit:
Here is an image showing how the second level is not centered.
And nothing complicated with the code:
<Fluent:MenuItem Header="Print Invoice" Icon="NavIcons\Print_32.png" />
Here are possible solutions for your problem.
Simple, but somewhat ugly.
Create an event handler in code behind for the Loaded event of your menu items.
<Fluent:MenuItem Loaded="MenuItem_Loaded"/>
In this event handler, you can find the control template parts manually and override their appearance:
private void MenuItem_Loaded(object sender, RoutedEventArgs e)
{
Fluent.MenuItem menuItem = sender as Fluent.MenuItem;
if (menuItem != null)
{
TextBlock textBlock = menuItem.Template.FindName("textBlockDesc", menuItem) as TextBlock;
if (textBlock != null)
{
textBlock.Visibility = System.Windows.Visibility.Collapsed;
}
textBlock = menuItem.Template.FindName("textBlock", menuItem) as TextBlock;
if (textBlock != null)
{
textBlock.VerticalAlignment = System.Windows.VerticalAlignment.Center;
}
}
}
This is a bad solution, don't do it like that. I've just shown it so you can get an idea how could you access the template parts if you wish to. These strings "textBlockDesc" and "textBlock" are the control template parts defined in the Fluent theme.
Create your own style and control template.
Since you can't inherit a control template, you have to copy it from the Fluent theme and put it in your resources. The disadvantage is that you'll have to manually resync that template with the original one if there will be an update.
I don't put an example here, because that solution isn't really good too.
Override the menu item style manually.
Set the style of your menu items manually to the "first level" menu items' style.
<Fluent:MenuItem Style="{DynamicResource ApplicationMenuStyle}"/>

WPF - Need to enable scrolling in a disabled DataGrid

My DataGrid columns are being added in code behind.
When the user is done editing rows and clicks on a Next button, DataGrid is disabled and user is taken to the next step which is in the same view..
The problem arises if user has a lot of rows and needs to scroll over the now disabled DataGrid to overview the rows.
I've tried wrapping the DataGrid (which is bound to a property that sets IsEnabled = false when user clicks on Next) in a ScrollViewer which gives me the desired effect but the scroll is then located outside the DataGrid which I find annoying.
I'm at my wits end and could really use some help how I should go about doing this.
I've also tried overriding the metadata for ScrollViewer which works somewhat but is unsafe from what I've read.
Any ideas?
Instead of using the IsEnabled property you can use the DataGrid.IsReadOnly property.
Mark the DataGrid as ReadOnly and apply the following style to get the appearance like disabled (if required).
<DataGrid.Style>
<Style TargetType="DataGrid">
<Style.Triggers>
<Trigger Property ="IsReadOnly" Value="True">
<Setter Property= "Foreground" Value="Gray"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Style>
I ended up using the IsReadOnly property on the DataGrid and bound it to IsEnabled.
This was an apparent problem at first because IsEnabled was true making the DataGrid read-only in the wrong state.
So I created a helper class to convert the bool to false to reflect the correct states (enabled/disabled).
The components in the DataGrid have their IsEnabled property databound also which gives me the proper disabled styles for them when DataGrid is read-only.
Thanks for the help guys!

AutoCompleteBox does not render correctly

I have an autoCompleteBox in my wpf window and I set ValidatesOnDataErrors binding property to True for selectedItem property of autoCompleteBox control.
When I show my wpf window by clicking on a ribbon Button, Validation Area of autocompletbox does not render correctly.
like the picture below:
but when I show window by clicking on a standard Wpf button it work correctly
like the picture below:
for more info I create and attached a sample source code:
sample of my problem
can anyone help me ?
Thanks.
You're seeing both the custom error UI defined in the AutoCompleteBox's control template and the standard error template in the adorner. You should disable the latter:
<Style TargetType="{x:Type sysctrls:AutoCompleteBox}">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
</Style>

WPF ComboBox Item tabbing behaviour

I am migrating some win forms panels to WPF.
In WinForms, you can tab into to the combo box using the keyboard, select an item by typing the first character and then hit tab again and the combo to lose focus.
In WPF the second tab will move the focus rectangle down the list, instead of moving onto the next control.
Is there a way to get the old behavior? Or has anyone implemented an ItemTemplate that achieves this behvaiour?
thanks
There is a ComboBoxItem which has an IsTabStop property.
So I just applied the appropriate style:
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="IsTabStop" Value="False"/>
</Style>

Categories

Resources