Can't set focus on first item of ListBox - c#

I can't set focus on first item of my ListBox. ListBox has some collection bound. It looks like, that first everything in code-behind doing its stuff then there is control initializing so I would have always -1 as SelectedIndex.
XAML
<Window x:Class="Labels.Szablony"
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:Labels"
mc:Ignorable="d"
Title="Labels" Height="350" Width="250" WindowStartupLocation="CenterScreen"
ResizeMode="CanMinimize" KeyDown="Window_KeyDown" Background="#FFF6A300" >
<Window.DataContext>
<local:LabelGridViewModel/>
</Window.DataContext>
<ScrollViewer VerticalScrollBarVisibility="Hidden" VerticalContentAlignment="Center"
VerticalAlignment="Center" Background="#FFF6A300">
<Grid Background="#FFF6A300" Name="labelGrid">
<ListBox x:Name="SzablonyBox" ItemsSource="{Binding LabelsCollection, IsAsync=True}"
HorizontalAlignment="Center" VerticalAlignment="Top"
MinWidth="100" MinHeight="100" BorderBrush="{x:Null}"
Background="{x:Null}" TextSearch.Text="BLABLAB"
TextSearch.TextPath="Name" IsTextSearchEnabled="True"
VerticalContentAlignment="Center" Margin="0 25 0 0"
Width="250" HorizontalContentAlignment="Center">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="PreviewKeyDown"
Handler="ListBoxItem_PreviewKeyDown"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel Width="214">
<TextBlock Text="{Binding Name}"
FontSize="12" Height="35"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Width="250"
TextAlignment="Center"/>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox x:Name="InputText"
Text="{Binding Path=Filter, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Center" Height="22" TextWrapping="Wrap"
VerticalAlignment="Top" Width="250" Background="#FFF6A300"
IsEnabled="False" BorderBrush="#FFF6A300"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Center"
Foreground="Black" SelectionBrush="{x:Null}"/>
</Grid>
</ScrollViewer>
What i'm trying to do looks like:
public Labels()
{
InitializeComponent();
LabelsBox.Focus();
LabelsBox.SelectedIndex = 0;
var item = LabelsBox.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem;
item.Focus();
}
Of course there is an exception, because item is null. Like I said SelectedIndex is always -1. What am I doing wrong ?

The ItemsSource Binding is asynchronous, so there are certainly not yet any items available while the constructor is running.
Change the Binding to be synchronous, i.e. the default behavior:
<ListBox ItemsSource="{Binding LabelsCollection}" ...>
You may also execute your initialization code as late as possible, by moving it to a Loaded event handler:
public Labels()
{
InitializeComponent();
...
Loaded += (s, e) =>
{
var item = (ListBoxItem)LabelsBox.ItemContainerGenerator.ContainerFromIndex(0);
item?.Focus();
};
}

Related

Button binding not working which is in Expander, which is in a listview

I have a strange issue. I have a listview which contains expander. That expander contains button. When I try to click on it - I am getting an error stating "Cannot find source: Element name".
When I remove CommandParameter from the code and place it again during the runtime - it works. Any ideas why that is happening? All TextBlocks are bind correctly and there are no issue, except for those buttons
Listview:
<ListView x:Name="customMeetingsListView"
Grid.Row="2"
ItemsSource="{Binding CustomMeetingsList}"
Style="{StaticResource CtMeetingsListView}"/>
List view item template:
<Style x:Key="CtMeetingsListView" TargetType="{x:Type ListView}">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Expander Background="Transparent">
<Expander.Header>
...
</Expander.Header>
...
<materialDesign:Badged Grid.Row="0"
HorizontalAlignment="Right"
Badge="{Binding RelatedFiles.Count}"
Padding="0 0 8 0">
<materialDesign:PopupBox
Background="Transparent"
StaysOpen="True">
<Button Background="{DynamicResource CardBackground}"
Margin="0 -8 0 -10"
BorderThickness="0"
Command="{Binding ElementName=customMeetingsListView, Path=DataContext.AddCaseFileCommand}"
CommandParameter="{Binding}">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="FileDocumentEditOutline"
VerticalAlignment="Center"
Foreground="DarkSlateGray"
Width="12" Height="12"/>
<TextBlock Margin="10 0 0 0"
Text="Add new"
Foreground="DarkSlateGray"
VerticalAlignment="Center"
FontSize="10"/>
</StackPanel>
</Button>
</materialDesign:PopupBox>
</materialDesign:Badged>
DataContext is bind via Prism:
<UserControl
...
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
...
</UserControl>
View model:
private DelegateCommand<CustomMeetingEntity> _addCaseFileCommand = null;
public DelegateCommand<CustomMeetingEntity> AddCaseFileCommand => _addCaseFileCommand ?? (_addCaseFileCommand = new DelegateCommand<CustomMeetingEntity>(AddCaseFile));
Regards,
Eddie

ObservableCollection not Sorting

I am writing an MVVM application but I am having trouble with an Observable Collection.
The ObservableCollection is held in the view model as:
private ObservableCollection<Participant> _initiativeList;
public ObservableCollection<Participant> InitiativeList
{
get { return _initiativeList; }
set
{
_initiativeList = value;
OnPropertyChanged("InitiativeList");
}
}
In the XAML I have a list box :
<ListBox x:Name="lvInitiativeList"
DockPanel.Dock="Top"
ItemsSource="{Binding Source={StaticResource InitiativeListCollection}}"
ItemTemplate="{StaticResource ResourceKey=ParticipantDisplayPanel}"
SelectedItem="{Binding Path=SelectedParticipant}"/>
The collectionViewSource it uses is:
<CollectionViewSource Source="{Binding Path=InitiativeList, Mode=OneWay}"
x:Key="InitiativeListCollection">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="InitiativeScore" Direction="Descending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
and the Item Template is:
<DataTemplate x:Key="ParticipantDisplayPanel">
<uc:ParticipantDisplayPanel/>
</DataTemplate>
the ParticipantDisplayPanel is a UserControl defined as:
<UserControl x:Class="InitiativeList.View.UserControls.ParticipantDisplayPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InitiativeList.View.UserControls">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="..\Resources\CommonStyles.xaml"/>
<ResourceDictionary Source="..\Resources\ConverterDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Border BorderBrush="{Binding Path=ActionState, Mode=OneWay, Converter={StaticResource BorderHighlight}}"
BorderThickness="3"
CornerRadius="10"
Background="{Binding Path=Kind, Mode=OneTime, Converter={StaticResource KindColor}}">
<StackPanel Orientation="Horizontal"
Width="450"
Height="50"
Background="Transparent">
<Border BorderBrush="Black"
BorderThickness="2"
Width="50"
Height="50"
CornerRadius="25"
Background="#FF8040">
<TextBlock x:Name="tbInitiative"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="30"
Text="{Binding Path=InitiativeScore,
Mode=OneWay,
Converter={StaticResource InitiativeScore}}"/>
</Border>
<TextBlock x:Name="tbName"
Background="Transparent"
Width="250"
Height="25"
FontFamily="Ariel"
FontWeight="Bold"
FontSize="20"
Text="{Binding Path=Name, Mode=OneWay}"/>
<TextBlock x:Name="Condition"
Background="Transparent"
Width="100"
Height="25"
Text="{Binding Path=Condition, Mode=OneWay}"/>
<Border BorderBrush="Black"
BorderThickness="2"
Width="50"
Height="50"
CornerRadius="25"
Background="{Binding Path=Healthiness, Mode=OneWay,
Converter={StaticResource HPBackground}}">
<TextBlock x:Name="tbHitPoints"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="25"
Text="{Binding Path=CurrentHitPoints, Mode=OneWay}"/>
</Border>
</StackPanel>
</Border>
</UserControl>
When I add items to the observable collection the items appear in the ListBox, and when I update properties of the elements the ParticipantDisplayPanels update to reflect the changed data. However the collection does not sort in response to these changes, unless I specifically call OnPropertyChanged for the list, something I was expecting to be done as part of the function of the ObservableCollection, or at least through the Set code on the InitiativeList Property.
It feels wrong to have to pepper the OnPropertyChanged calls throughout the code. Am I doing something wrong? all my searches on the internet haven't turned up an example of an Observable Collection that I can relate to how I've written my code.
Any pointers as to what is going wrong would be much appreciated.
I want to implement some custom sorting on Observable collection and I did it like below and then bind:
ItemsSource="{Binding CollectionView}"...
List<SortDescription> SortDescriptions = new List<SortDescription>();
SortDescriptions.Add(new SortDescription("Field1", ListSortDirection.Ascending));
SortDescriptions.Add(new SortDescription("Field2", ListSortDirection.Ascending));
SortDescriptions.Add(new SortDescription("Field3", ListSortDirection.Ascending));
SortDescriptions.Add(new SortDescription("Field4", ListSortDirection.Ascending));
CollectionViewSource collectionViewSource = new CollectionViewSource();
public ICollectionView CollectionView
{
get
{
collectionViewSource.Source = <YourObservableCollection>;
if (SortDescriptions != null)
{
foreach (SortDescription sd in SortDescriptions)
{
collectionViewSource.View.SortDescriptions.Add(sd);
}
}
collectionViewSource.View.Refresh();
return collectionViewSource.View;
}
}

WPF: How to access element in ResourceDictionary code behind

In my application I have a control which renders a number of blocks on a timeline view (like a calendar). One can provide a template for the blocks by giving the timeline an appropriate DataTemplate.
I would like to separate the block DataTemplate from the main timeline view, putting the block into its own XAML. As such, I've created a XAML for the Block (called Block.xaml) and wrapped the DataTemplate inside a ResourceDictionary, inside this XAML.
I've added a code behind to the XAML (called Block.xaml.cs) in which I need to access some of the elements in the block. The issue is that ResourceDictionaries seem to hide the elements from the codebehind such that I can't access them. I can't use a UserControl instead - this seems to not work.
How can I access the elements of the Block DataTemplate from the code behind?
Many thanks in advance for your help.
Block.xaml:
<ResourceDictionary x:Class="Project.Windows.MainInterface.TimelinePanel.Block" 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:local="clr-namespace:Project.Windows.MainInterface.TimelinePanel" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:converters="clr-namespace:Project.Converters" >
<DataTemplate x:Key="ItemBlockTemplate">
<Grid Name="BlockParent" Width="Auto" Height="Auto" MinHeight="50" ClipToBounds="True" SizeChanged="BlockParent_OnSizeChanged">
<Border Panel.ZIndex="3" BorderBrush="{DynamicResource BackgroundGreyLight}" BorderThickness="1" CornerRadius="1" />
<Grid Margin="1" Background="{DynamicResource BlockBackgroundGradient}" d:LayoutOverrides="Width">
<TextBlock x:Name="blockName" Height="20" Margin="4,0,4,0" Padding="3" VerticalAlignment="Top" Panel.ZIndex="3" FontSize="10" Foreground="{DynamicResource TextLight}" Text="{Binding blockName}" TextTrimming="CharacterEllipsis" Visibility="Visible" />
<TextBlock x:Name="Duration" Margin="0,2,4,2" Padding="0,0,3,0" HorizontalAlignment="Right" VerticalAlignment="Bottom" Panel.ZIndex="5" FontSize="10" Foreground="{DynamicResource TextLight}" Text="{Binding FormattedDuration}" ToolTip="{Binding Duration}" />
<Grid Background="#FF0FA8FF" Opacity="0.7" />
</Grid>
</Grid>
</DataTemplate>
Snippet of the Timeline in the main interface:
...
<timeLineTool:TimeLineControl x:Name="Timeline" Height="50" MinWidth="50" Margin="0,0,12,0" HorizontalAlignment="Left" VerticalAlignment="Top" Items="{Binding Timeline}" SnapsToDevicePixels="True" UnitSize="{Binding UnitSize}" UseLayoutRounding="True">
<timeLineTool:TimeLineControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:BlockItemViewModel}">
<ContentControl>
<ContentPresenter Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Content="{Binding}" ContentTemplate="{StaticResource ItemBlockTemplate}" />
</ContentControl>
</DataTemplate>
</timeLineTool:TimeLineControl.ItemTemplate>
</timeLineTool:TimeLineControl>
...
...If I could use a UserControl instead of a ResourceDictionary for my Block, this would solve the problem, as all elements are automatically publicly available in the code behind for usercontrols.
Sample XAML:
<Window.Resources>
<ControlTemplate x:Key="ResourceName" TargetType="{x:Type Label}">
<Label Foreground="White" Content="{iconPacks:PackIconFontAwesome plug,Height=40,Width=40}"/>
</ControlTemplate>
</Window.Resources>
Code behind
ControlTemplate Dictionary:
private Dictionary<string, ControlTemplate> collection
{
get
{
Dictionary<string, ControlTemplate> controlTemplates = new Dictionary<string, ControlTemplate>();
controlTemplates.Add("ResourceName", FindResource("ResourceName") as ControlTemplate);
return controlTemplates;
}
}
Use ControlTemplate:
Label LBDisConnect = new Label();
LBDisConnect.Template = collection["ResourceName"];
LoginInfo.Children.Add(LBDisConnect);

c# wpf getting input from textbox in dynamically generated DataTemplate objects

I'm a newcomer to C# WPF programming, and I'm having difficulty (spent a whole day on this) figuring out how to create a system where:
1) A collection of UI elements (in a groupbox) is generated with a click of a button.
2) The groupbox has a textbox (for int inputs) and a combobox (selection among strings). I need to populate combobox with the elements of a list.
I need to take input from the textbox and selection from combobox and place it in a List of my structs Rules{ String topic; int number}.
This needs to be done for as many of the groupboxes the user generates.
The main question I have is, how do I access these comboboxes to populate them? How Do i get input from them?
xaml
<Window x:Class="ExamMaker.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:ExamMaker"
mc:Ignorable="d"
Title="Exam Preparation" Height="350" Width="525"
Closing="Window_Closing">
<Window.Resources>
<DataTemplate x:Key="ruleTemplate">
<GroupBox x:Name="Rulebox" Header="Rule " HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Top" Height="56" Width="468">
<Grid HorizontalAlignment = "Left" Height="36" Margin="0,0,-2,0" VerticalAlignment="Top" Width="458">
<Label x:Name="TopicRuleLabel" Content="Topic:" HorizontalAlignment="Left" Margin="5,4,0,0" VerticalAlignment="Top" Height="28"/>
<TextBox x:Name="NumberRuleTextBox" HorizontalAlignment="Left" Height="22" Margin="240,9,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="30" />
<ComboBox x:Name="RuleComboBox" HorizontalAlignment="Left" Margin="50,9,0,0" VerticalAlignment="Top" Width="120"/>
<Label x:Name="NumberRuleLabel" Content="Number:" HorizontalAlignment="Left" Margin="179,4,0,0" VerticalAlignment="Top" Height="28"/>
</Grid>
</GroupBox>
</DataTemplate>
</Window.Resources>
<Grid>
<TabControl x:Name="tabControl" HorizontalAlignment="Left" Height="319" VerticalAlignment="Top" Width="517">
<TabItem Header="Exam Preparation">
<Grid Background="#FFE5E5E5" Margin="0,0,0,0">
<ListView x:Name="listView" ItemsSource="{Binding Path=examQS}">
<ContentControl ContentTemplate="{StaticResource ruleTemplate}">
</ContentControl>
</ListView>
</Grid>
</TabItem>
<TabItem Header="Question Form" Margin="-2,0,0,0" HorizontalAlignment="Left" Width="95">
</TabItem>
<TabItem Header="Setup" HorizontalAlignment="Left" Height="20" VerticalAlignment="Top" Width="54">
</TabItem>
</TabControl>
</Grid>
</Window>
As for the c#, well I only have one Observable collection in there and some methods for adding and removing items from it.
Ok, based on what I see, I think here is how you can go about this:
ItemsSource="{Binding Path=examQS}"
assuming you have property ObservableCollectionexamQS
1. Define a property in examQs lets say "comboItemSource"
change this line in your DataTemplate by adding a binding on ItemSource: <ComboBox x:Name="RuleComboBox" HorizontalAlignment="Left" Margin="50,9,0,0" VerticalAlignment="Top" Width="120" ItemSource="{Binding Path=comboItemSource} />
Change to use ItemTemplate
<ListView x:Name="listView" ItemsSource="{Binding Path=examQS}" ItemTemplate="{StaticResource ruleTemplate}"/>
I think the above should work.

Items in ListBox not automatically updating

The problem is that the user interface (the ListBox) is not updated when new items enter its collection. I've a ListBox which is defined as follows:
<ListBox x:Name="ui_UserList" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SelectionChanged="ui_UserList_SelectionChanged" ItemsSource="{Binding chatUsers}" Grid.ColumnSpan="3" Margin="10,179,10,81" DataContext="{Binding}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent">
<TextBlock Text="{Binding nickname}" HorizontalAlignment="Center" TextAlignment="Center" FontSize="42" Grid.Row="0" Grid.Column="0" Foreground="Black" VerticalAlignment="Top" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The itemsource ChatUsers is an ObservableCollection. This was originally designed as an application for Windows Phone 8, where the ListBox equivalent works as expected (it updates when an item enters the collection).
Is there something about the ListBox that I've missed?
Ok, looks like I needed to set the DataContext explicitly even though it never complained about it.
The only change is this:
<ListBox x:Name="ui_UserList" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SelectionChanged="ui_UserList_SelectionChanged" ItemsSource="{Binding chatUsers}" Grid.ColumnSpan="3" Margin="10,179,10,81" DataContext="{StaticResource ChatUsersViewModel}">
.....
</ListBox>

Categories

Resources