I've created a border and inside it I put a combox. After that, I also added a checkbox but then VS complained that there's only one child property allowed. It's possible that I'm asking the wrong question.
Should I use a different control for "keeping stuff together"? Which one would that be?
If the border is correct for the purpose, what am I doing incorrectly, then?
<Border BorderBrush="Black" BorderThickness="1" ... >
<ComboBox x:Name="comboBox" ... />
<CheckBox x:Name="checkBox" ... />
</Border>
Border is a fine control to use if you want a border around your content, but its not a Panel, so it can only have one child. Simply do something like:
<Border BorderBrush="Black" BorderThickness="1" ... >
<StackPanel>
<ComboBox x:Name="comboBox" ... />
<CheckBox x:Name="checkBox" ... />
</StackPanel>
</Border>
Now the Border only has one child, and your other elements are laid out by a Panel element which can have multiple children.
Related
I have a user control with many sub controls within a grid. Since there are many controls per row, I'm controlling the visibility of the controls by setting the row height of their containing row to 0 (to hide them).
I'm using a validation template on some of these controls and displaying an icon next to the control using AdornedElementPlaceholder.
Since I'm not actually setting the visibility property of the adorned control, but instead hiding the row, the validation icon is not collapsed with the rest of the control.
Here's an abridged version of my XAML code:
<UserControl
<UserControl.Resources>
<ControlTemplate x:Key="ValidationTemplate" TargetType="Control">
<DockPanel>
<Grid
Width="16"
Height="16"
Margin="10,0,0,0"
VerticalAlignment="Center"
DockPanel.Dock="Right">
<Image Source="{x:Static icons:Icons.ValidationIcon}" ToolTip="{Binding Path=ErrorContent}" />
</Grid>
<AdornedElementPlaceholder />
</DockPanel>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="{Binding Path=ScheduleType, Mode=OneWay, Converter={StaticResource ScheduleTypesToGridRowHeightConverter}, ConverterParameter={x:Static local:ScheduleTypes.Other}}"/>
<RowDefinition Height="{Binding Path=ScheduleType, Mode=OneWay, Converter={StaticResource ScheduleTypesToGridRowHeightConverter}, ConverterParameter={x:Static local:ScheduleTypes.Fixed}}"/>
<RowDefinition Height="{Binding Path=ScheduleType, Mode=OneWay, Converter={StaticResource ScheduleTypesToGridRowHeightConverter}, ConverterParameter={x:Static local:ScheduleTypes.Weekly}}"/>
<RowDefinition Height="{Binding Path=ScheduleType, Mode=OneWay, Converter={StaticResource ScheduleTypesToGridRowHeightConverter}, ConverterParameter={x:Static local:ScheduleTypes.FreeText}}"/>
</Grid.RowDefinitions>
<controls:DateInputBox
Grid.Column="2"
Grid.Row="5"
Height="28"
HorizontalAlignment="Left"
Watermark=""
Width="110"
Text="{Binding StartDateText, ValidatesOnDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
Validation.ErrorTemplate="{StaticResource ValidationTemplate}"
VerticalAlignment="Center"
ParseComplexDates="True"/>
</Grid>
</UserControl>
From what I understand from a little research is that the validation icon is being displayed in the adorner layer, so doesn't collapse with the rest of the controls.
I'm now thinking that the "row height visibility pattern" was maybe not the best approach ;-) Is there a way I can get this to work without having to completely change my design? I do have a workaround using my view model but I'd like to explore other options first.
If you really whant to stick with the design, you could remove and add the adornents depending of what you whant to display. However, this would be pretty messy and defeat the point of sticking with the current desing for simplicity in the first place.
The concept of hiding elements by setting their parent element size to zero is indeed not the best option. Partly because of the exact issue you mentioned. (The adornents visibility is dependent on its owners visibility. And the owner elements visibility is visible, there is just no space to render it.)
A better option would be to only show whatever is to be shown. An easy way to accomplish this would be to encapsulate all the elements you whant to hide/show together inside one element or user control and then hide or show only that parent element or user control.
This could for instance look like this:
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Border Grid.Row="1" Visibility="{Binding FixedIsVisible, Converter={StaticResource BoolToVis}">
<!-- fixed shedule content here -->
</Border>
<Border Grid.Row="1" Visibility="{Binding WeeklyIsVisible, Converter={StaticResource BoolToVis}">
<!-- weekly shedule content here -->
</Border>
<Border Grid.Row="1" Visibility="{Binding FretextIsVisible, Converter={StaticResource BoolToVis}">
<!-- free text shedule content here -->
</Border>
</Grid>
By using some other converter you also yould directly bind you ScheduleType so you dont need to touch your view model.
A maybe even better option would be to make it so that only the elements you need at a time exist inside the view. This could be acomplished by defining different user controls and then have your grid line contain only the desired control at a time. (I might add an example for this later when i have time to do so.)
I got a problem with the design of my WPF program. My XAML looks like this:
<StackPanel Orientation="{Binding Orientation}">
<Border ... />
<Border ... />
<Border ... />
<Border Margin="2"
VerticalAlignment="Stretch"
CornerRadius="3"
Padding="4">
<WrapPanel>
<TextBlock VerticalAlignment="Center"
Text="Time Range:"
Width="66" />
<controls:WinFormsWrapper EndDateTime="{Binding EndDateTime,Mode=TwoWay}"
InitialEndDateTime="{Binding InitialEndDateTime}"
InitialStartDateTime="{Binding InitialStartDateTime}"
StartDateTime="{Binding StartDateTime,Mode=TwoWay}"/>
</WrapPanel>
</Border>
<Border ... />
</StackPanel>
Inside The WrapPanel you can see there is my WinFormsWrapper. In my Viewmodel i got a property Orientation which will determine how to Orientate the StackPanel. I want the WrapPanel now to fill the whole control horizontally if the Orientation is set to vertical and vice versa.
Does anyone know a good way to do this?
EDIT:
The Type of the property is System.Windows.Controls.Orientation and the possible values are: System.Windows.Controls.Orientation.Vertical and System.Windows.Controls.Orientation.Horizontal.
If you set a Background to your WrapPanel the panel is full size.
I think that you should use a DockPanel instead of your WrapPanel with the property value LastChildFill="True".
Your error comes from invalid values. Set a valid start value to your Orientation property
private Orientation orientation = Orientation.Horizontal;
I thought I cooked up something rather brilliant, but it's not working (yet!).
I am trying to get rid of all code behind in a SettingsDialog where a SettingsGroup can be selected by the user, which will consequently be visualized to the right of ListView (a similar settings dialog as Visual Studio has).
I was tipped to use a ContentPresenter, which I did, but then later realized that the tipper probably meant to rely on only XAML to get the job done.
This is what I got so far.
Declaring the SettingsGroups in XAML:
<Grid.Resources>
<w:DefinePathsUserControl x:Key="DefinePathSettingsGroup"></w:DefinePathsUserControl>
<w:HideShowTvShowsUserControl x:Key="HideShowTvShowsSettingsGroup"></w:HideShowTvShowsUserControl>
</Grid.Resources>
Add the left hand side SettingsGroup selector (a simple ListView):
<ListView
x:Name="SettingsGroupSelector"
Grid.Row="0"
Grid.Column="0">
<ListViewItem
x:Name="PathSetting"
Tag="{StaticResource DefinePathSettings}"
Content="Path"/>
<ListViewItem
x:Name="HideShowTvShowsSetting"
Tag="{StaticResource HideShowTvShowsSettings}"
Content="Hide/Show TV Shows"/>
</ListView>
And then I thought I could simply bind the ContentPresenter to the tag of the selected item in the ListView, like:
<ContentPresenter
x:Name="SettingsContentPanel"
Grid.Row="0"
Grid.Column="2"
Grid.ColumnSpan="2"
Content="{Binding Source=SettingsGroupSelector, Path=SelectedItem.Tag}" />
Unfortunately for me, this does not show anything in my ContentPresenter. I also don't get any errors in my output window.
Who can help me further?
Change
<ContentPresenter
x:Name="SettingsContentPanel"
Grid.Row="0"
Grid.Column="2"
Grid.ColumnSpan="2"
Content="{Binding Source=SettingsGroupSelector, Path=SelectedItem.Tag}" />
to this
<ContentPresenter
x:Name="SettingsContentPanel"
Grid.Row="0"
Grid.Column="2"
Grid.ColumnSpan="2"
Content="{Binding ElementName=SettingsGroupSelector, Path=SelectedItem.Tag}" />
More information on specifying the Binding Source
I have a usercontrol that contains 2 rows. 1st row has a label and 2nd row has a scrollviewer with a canvas:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="TITLE" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Name="label1" VerticalAlignment="Top" FontSize="26" />
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<Canvas Background="White" />
</ScrollViewer>
</Grid>
In my main window.xaml I'm trying to add this user control and then add items to it's canvas.
<local:UserCanvas>
<label Content="Test" />
</local:UserCancas>
There problem here is that when I had that label in there it just overrides the "TITLE" label in row 1 of the user control. How do I add things so that they are placed on the cavas of the UserControl?
Instead of defining the Content in your UserControl, define the UserControl.ContentTemplate
For example, instead of writing
<UserControl ...>
<Grid>
...
<Canvas />
...
</Grid>
</UserControl>
use
<UserControl ...>
<UserControl.ContentTemplate>
<DataTemplate>
<Grid>
...
<Canvas>
<ContentPresenter Content="{TemplateBinding Content}"/>
</Canvas>
...
</Grid>
</DataTemplate>
</UserControl.ContentTemplate>
</UserControl>
If you use the first syntax, then specifying the Content when you use your UserControl will result in the existing Content getting overwritten, so your rendered Visual Tree ends up looking like this:
<local:UserCanvas>
<label Content="Test" />
</local:UserCancas>
By using the 2nd syntax, you're wrapping the Content in your ContentTemplate, so the rendered Visual Tree ends up looking like this:
<local:UserCanvas>
<Grid>
...
<Canvas>
<label Content="Test" />
</Canvas>
...
</Grid>
</local:UserCanvas>
I would try adding a public property (that you check and respond to in the user control's Page_Load()) and/or public method (that you just call from outside the control) to the user control which you can then access from your main program. Which way to go depends a bit on how complicated the actions you're needing to take will be. It looks to me like this will be simple enough to handle through the public property + Page_Load() method.
I've got following code. Why are my items always clipped after about 70px
<sdk:HierarchicalDataTemplate x:Key="OptionsTemplate">
<CheckBox IsTabStop="False" Content="{Binding EnumValue}" IsChecked="{Binding IsSelected, Mode=TwoWay}" />
</sdk:HierarchicalDataTemplate>
<sdk:HierarchicalDataTemplate x:Key="EnumOptionsTemplate" ItemsSource="{Binding Values}" ItemTemplate="{StaticResource OptionsTemplate}">
<TextBlock Text="{Binding EnumType}"/>
</sdk:HierarchicalDataTemplate>
<sdk:TreeView x:Name="FilterTreeView" ItemsSource="{Binding GeoObjectFilter}" ItemTemplate="{StaticResource EnumOptionsTemplate}">
<sdk:TreeView.Template>
<ControlTemplate TargetType="sdk:TreeView">
<StackPanel Background="Transparent">
<ItemsPresenter x:Name="TreeItems" />
</StackPanel>
</ControlTemplate>
</sdk:TreeView.Template>
</sdk:TreeView>
Thanks in advance!
Ho yes i had same issue when redefining the TreeView Template. By the way, i'm not sure you need to, since StackPanel is the Default Template. I got my (wrappanel) template to work by setting a style for ItemsPanel rather than redifining it. And i had to define some width also. Seems the only way to make the Treeview to scale is to bind the width.
See the answer i made to my question here :
https://stackoverflow.com/a/8802718/856501