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.
Related
I have a desktop application I am building in C# with XAML. I am having troube with the XAML side of things, and how its displayed on the preview compared to the actual program view.
I have tried putting the elements I am using into a grid, a stackPanel but it still has the same issue. Here is what the program should look like:
And how it actually appears in the program:
<Page x:Class="project.PayFees"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:mosque"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Pay Fees">
<Grid>
<Grid>
<Label Margin="67,90,641,328" Content="Amount Paid"/>
<Button Command="{Binding PayFees}" Content="Pay Fees" Margin="584,405,10,10"
RenderTransformOrigin="1.172,-3.328"/>
<Label Margin="67,62,691,360" Content="Date" RenderTransformOrigin="0.684,-0.03"/>
<TextBox x:Name="StudentID" Text="{Binding StudentID}" Width="130"
Margin="159,126,511,290" RenderTransformOrigin="-0.285,-6.056" />
<Label Content="Student ID" RenderTransformOrigin="3.77,3.251" Margin="67,126,663,292"/>
<TextBox x:Name="AmountPaid" Text="{Binding AmountPaid}" Width="130"
Margin="159,90,511,328" RenderTransformOrigin="0.039,0.004"/>
<TextBox Text="{Binding Date}" HorizontalAlignment="Left" Margin="159,52,0,0"
VerticalAlignment="Top" RenderTransformOrigin="2.704,6.1" Width="130" Height="32"/>
<Button Content="Load Student" HorizontalAlignment="Left" Margin="306,136,0,0"
VerticalAlignment="Top" Width="86" Height="22" Click="Button_Click"/>
<Label x:Name="studentName" Content="" HorizontalAlignment="Left" Margin="159,165,0,0"
VerticalAlignment="Top" Width="130"/>
</Grid>
</Grid>
This is my XAML code.
I can't figure out why this is happening - any advice is appreciated.
I want to make change main panel content when I choice action in menu button.
Like main content page, setting page, content page on Main panel (in code used grid x:Name="main_~~~)
It for use just can make 3 and control visibility??
or Can use include like xml at Android and change include target??
( ex > includelayout="#layout/app_bar_main")
Mainwindow.xaml
<Window x:Class="M_C.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:M_C"
mc:Ignorable="d"
Title="MainWindow"
Width="1024" Height="768"
WindowStyle="None"
WindowState="Maximized"
WindowStartupLocation="CenterScreen">
<Grid x:Name="wide_Out" Background="#000000">
<Viewbox Stretch="Uniform">
<Grid Width="1024" Height="768" VerticalAlignment="Top">
<DockPanel x:Name="L_black" HorizontalAlignment="Left"
Height="768" LastChildFill="False" VerticalAlignment="Top" Width="62"
Background="#FF242424">
<Button Margin="15,8,0,0" Height="40"
VerticalAlignment="Top" Width="30"/>
</DockPanel>
<DockPanel x:Name="T_blue" HorizontalAlignment="Left"
Height="84" LastChildFill="False" Margin="62,0,0,0" VerticalAlignment="Top"
Width="968" Background="#FF248BC7">
<TextBlock Margin="200,5,200,0" Height="70"
TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="554"/>
</DockPanel>
<DockPanel x:Name="L_blue" HorizontalAlignment="Left"
Height="685" LastChildFill="False" Margin="62,83,0,0"
VerticalAlignment="Top" Width="82" Background="#FF248BC7"/>
<DockPanel x:Name="R_blue" HorizontalAlignment="Left"
Height="685" LastChildFill="False" Margin="940,83,0,0"
Background="#FF248BC7" Width="84"/>
<DockPanel x:Name="B_blue" HorizontalAlignment="Left"
Height="90" LastChildFill="False" Margin="143,678,0,0"
VerticalAlignment="Top" Width="799" Background="#FF248BC7">
<Image Margin="250,15,250,15" Height="70"
VerticalAlignment="Top" Width="290" />
</DockPanel>
<!--<DockPanel x:Name="main_content_panel"
HorizontalAlignment="Left" Height="594" LastChildFill="False"
Margin="144,84,0,0" VerticalAlignment="Top" Width="790">-->
<Grid x:Name="main_con_body" Margin="143,82,84,88"
Width="798" Height="594" Background="#ffffff">
</Grid>
<!--</DockPanel>-->
</Grid>
</Viewbox>
</Grid>
</Window>
You can Define Frame inside Your Window and navigate between as many page you want:
<Frame Name="FrameWithinGrid" >
</Frame>
and on button Click you can simply navigate:
private void button1_Click(object sender, RoutedEventArgs e)
{
FrameWithinGrid.Navigate(new System.Uri("Page1.xaml",
UriKind.RelativeOrAbsolute));
}
to know more See here
MVVM Approach
Make main_con_body be a ContentControl
Make Window's DataContext a viewmodel
Bind main_con_body's Content property to a viewmodel property of the data context
Define different DataTemplates for the various types of viewmodels that might be present
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();
};
}
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);
I have a class PC that contains Image, Label (with XAML design) and I want to get a list of PCs in ListBox in other class.
I tried this, but I get error System.Windows.Markup.XamlParseException:
pc p = new pc();
list_pc.Items.Add(p);
(where list_pc is a ListBox)
This is the XAML for a single PC:
<Window
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" mc:Ignorable="d"
x:Class="TnCyberCafe.pc"
Title="pc"
SizeToContent="WidthAndHeight"
ShowInTaskbar="False"
WindowStartupLocation="CenterScreen"
WindowStyle="None"
AllowsTransparency="True"
Background="Transparent" Width="95" Height="104.982">
<Grid HorizontalAlignment="Left" Margin="0,10,-15,10" Width="110">
<Image x:Name="image" HorizontalAlignment="Left" Height="96" VerticalAlignment="Top" Width="100" Source="Resources/aaa.png" RenderTransformOrigin="0.5,0.26" Margin="0,-16,0,0"/>
<Label Content="Label" HorizontalAlignment="Left" Height="25" Margin="20,70,0,-10" VerticalAlignment="Top" Width="45"/>
</Grid>
</Window>
This is the XAML for my list_pc:
<ListBox x:Name="liste_pc" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
List PCs
</ListBox>
Your first question regarding the System.Windows.Markup.XamlParseException:
As Garry Vass mentioned something went wrong, but does not tell you exactly what happened. If you are developing in Visual Studio, Click on Exceptions under Debug Tab and enable Common Language Runtime Exceptions. This will point you to the Error Code.
For the second question you should have databindings and ListBox Itemtemplate as below
<ListBox x:Name="liste_pc" ItemsSource="{Binding PCList}" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding PCImageSource}" />
<Label Content="{Binding Path=PCName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
where PCList is the observable collection of PC Class object items