Show DevExpress DXTabControl tabs at the bottom in XAML - xaml

Does anyone know how to use the DevExpress DXTabControl in XAML and set it up so that the tabs appear at the bottom? Here is what I have so far but the tabs show up at the top. The DevExpress documentation does not have an example of this. Intellisense does not give me anything intuitive.
<dx:DXTabControl>
<dx:DXTabItem Header="Main">
<dxdo:DockLayoutManager>
<dxdo:LayoutGroup>
<dxdo:LayoutPanel Caption="TaskList">
<views:DxTaskList x:Name="Tasklst" />
</dxdo:LayoutPanel>
<dxdo:LayoutPanel Caption="TaskDetails">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Focusable="False">
<StackPanel>
<views:TaskDetails x:Name="TaskDtls"/>
</StackPanel>
</ScrollViewer>
</dxdo:LayoutPanel>
</dxdo:LayoutGroup>
</dxdo:DockLayoutManager>
</dx:DXTabItem>
</dx:DXTabControl>

For anyone who might be stumped at something not-so-obvious, here is the XAML solution I was looking for. Yes, the property was obviously called HeaderLocation but DevExpress' documentation does not give any XAML examples on this. So here is what I came up with that solved my case:
<dx:DXTabControl>
<dx:DXTabControl.View>
<dx:TabControlMultiLineView HeaderLocation="Bottom"/>
</dx:DXTabControl.View>
<dx:DXTabItem Header="Main">
<dxdo:DockLayoutManager>
<dxdo:LayoutGroup>
<dxdo:LayoutPanel Caption="TaskList">
<views:DxTaskList x:Name="Tasklst" />
</dxdo:LayoutPanel>
<dxdo:LayoutPanel Caption="TaskDetails">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Focusable="False">
<StackPanel>
<views:TaskDetails x:Name="TaskDtls"/>
</StackPanel>
</ScrollViewer>
</dxdo:LayoutPanel>
</dxdo:LayoutGroup>
</dxdo:DockLayoutManager>
</dx:DXTabItem>
</dx:DXTabControl>
As you can see you're supposed to add the View property and then assign it a value, which I used a TabControlMultiLineView, and that object had a HeaderLocation property to which I set it to one of the valid enums. When I did this, the tabs appeared at the bottom.

Related

How to change the tab index in avalonia ui

In Avalonia Ui,
I have multiple layouts in my ui and I want a very specific tab order,
something like
<TextBox Tabindex="2">
<StackPanel>
<TextBox Tabindex="1">
</StackPanel>
<TextBox Tabindex="0">
that would result in using the tab-key cycling from bottom to top.
Is this possible? I found nothing.
I don't think so. KeyboardNavigation.TabIndex is not implmented yet: https://github.com/AvaloniaUI/Avalonia/issues/3025.
You have some limited Control using the functions provided in KeyboardNavigation and by using another control, for example a DockPanel or a Relative Panel.
Here is a very basic example for how you can use a DockPanel to do what you wish to:
<DockPanel LastChildFill="False"
VerticalAlignment="Top"
Name="TabOrderConatiner">
<TextBox Name="First" Tag="2" DockPanel.Dock="Top"></TextBox>
<TextBox Name="Third" Tag="0" DockPanel.Dock="Bottom"></TextBox>
<TextBox Name="Second" Tag="1" DockPanel.Dock="Top"></TextBox>
</DockPanel>
However it is like I said above limited compared to what TabIndex can provide.
Apart from that you should also be able to set the first TabItem when the container becomes active like that from your code-behind:
var tabOrderContainer = this.FindControl<DockPanel>("TabOrderConatiner");
var initialElement = this.FindControl<TextBox>("Third");
KeyboardNavigation.SetTabOnceActiveElement(tabOrderContainer, initialElement);
but I did not manage to get this to work...

{Binding ElementName=...} does not work from any CompositeTransform property

I have the following code in which I hide a WebView just under the main Grid (LayoutRoot) so I can do a sliding animation later:
<Page...>
<Grid x:Name="LayoutRoot">
...
<Grid x:Name="ContentRoot">
...
</Grid>
<WebView...>
<WebView.RenderTransform>
<CompositeTransform TranslateY="{Binding ElementName=LayoutRoot,
Path=ActualHeight}"/> <!--Does not work-->
</WebView.RenderTransform>
</WebView>
</Grid>
</Page>
When I first type the {Binding ElementName=...} line into the designer, the WebView appears just below the Grid like it should. However, when I rebuild the solution or run the app, the WebView simply obscures the whole LayoutRoot.
This will happen regardless of what I am binding to/whatever the control is; however, binding to the exact same expression will show up properly in the designer and in the phone. To demonstrate what I am saying:
<Button Width="{Binding ElementName=LayoutRoot, Path=ActualHeight}"> <!--Works perfectly, both on designer and phone-->
<Button.RenderTransform>
<CompositeTransform SomeProperty={Binding ElementName=SomeElement, Path=SomePath}"/> <!--This does not work-->
</Button.RenderTransform>
</Button>
Is there any way to bind to LayoutRoot.ActualHeight short of writing C# code for this?
One problem you have is you are trying to bind to ActualHeight which is not a dependency property nor an observable (INotifyPropertyChanged) property, so the binding is only evaluated once when it's first created.

Empty LongListSelector has infinite length

I have a LongListSelector which is inside a StackPanel. when this LLS is empty, it has infinite length and elements which are at the bottom of it can't be seen.
<StackPanel Orientation="Vertical">
<phone:LongListSelector>
</phone:LongListSelector>
</StackPanel>
but when I set it's ItemsSource, it gets fine. I tried assigning it's VerticalAlignment to top, but didn't solved the issue
How to make it's size not fill the form?
(I've edited this post to make it better)
First of all lets describe the problem you have, to do it we will use:
PROBLEM: infinite length of LongListSelector (LLS)- to be honest, it isn't a problem and it works like it should. Because LLS can have many many items and can be very long as its name says. The problem is that you use it in StackPanel without fixing its Height.
SOLUTIONS:
The first is very simple - just set the height of LLS. You will be sure that what should be below LLS, will be there. Like #Chris W mentioned - using LLS in StackPanel is not most forunate and can cause many problems - so avoid it.
<StackPanel Orientation="Vertical">
<phone:LongListSelector Height="300"/>
<TextBlock Text="Something/>
</StackPanel>
The most elegant and the best solution (also what #Chris W suggested) - to put your LLS into Grid. That way has many advantages and with Rowdefinitions your program will be independent of Phone resolution - all your controls will be there, were they should be.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="8*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<phone:LongListSelector Width="100" Grid.Row="0"/>
<TextBlock Text="Something" Grid.Row="1"/>
</Grid>
The third solution is not as good ad previous, but shows other way to manage your Controls. You can override the way LLS is measured. But with this method you have to watch out for example: it will work ok with the problem, unless you add so many items that your Controls will be pushed off the screen. Also you will have to watch out for this.Width, which has to be defined. So many additional conditions you have to check, of course you can add more modifications and it will work, but as I said it's not as good as previous solutions.
namespace Extensions
{
public class LongListSelectorEx : LongListSelector
{
protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
{
if (this.ItemsSource == null)
return new System.Windows.Size(this.Width, 0);
if (this.ItemsSource.Count <= 0)
return new System.Windows.Size(this.Width, 0);
return base.MeasureOverride(availableSize);
}
}
}
In your xaml you have to add:
<phone:PhoneApplicationPage
// something before
xmlns:common="clr-namespace:Extensions"
// other things
>
<StackPanel Orientation="Vertical">
<common:LongListSelectorEx Width="200"/>
<TextBlock Text="Something/>
</StackPanel>

Binding events to buttons in an ItemsControl

I have a windows phone 7 app with some xaml that looks like:
<Grid x:Name="ContentGrid" Grid.Row="1">
<ItemsControl x:Name="MyView" ItemTemplate="{StaticResource MyInner}"/>
</Grid>
The item template here looks like:
<DataTemplate x:Key="MyInner">
<ItemsControl ItemsSource="{Binding}" ItemTemplate="{StaticResource MyInner_Item}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</DataTemplate>
And finally, the MyInner_Item template looks like:
<DataTemplate x:Key="MyInner_Item">
<Button x:Name="MyButton">
<Button.Template>
<ControlTemplate>
<Border HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="myborder">
<Image Source="{Binding Path=ImageUri}" Width="{Binding Path=Width}" Height="{Binding Path=Height}" Stretch="Fill" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
So, it's an ItemsControl, which contains an ItemsControl, which contains buttons. This essentially creates a 2D array of buttons.
What I want to do is add an event handler to the Click event of the buttons.
Here's the catch: the code that sits behind this is written in F#. I can't, to the best of my knowledge, specify my event handler in the XAML, as F# doesn't talk to WPF in any nice way. So I need to add my event handler(s) manually in code.
Is there an easy way of doing this?
Currently, I have some F# which looks like:
let myView : ItemsControl = this?MyView
do myView.ItemsSource <- viewModel.BoardData
Here, the BoardData is a list of lists.
I was wondering if it's possible to loop through the controls in the ItemsControl, to add my event handlers? I'm having a bit of trouble doing this though. For example, in the following:
let container = myView.ItemContainerGenerator.ContainerFromItem(myView.Items.[0])
...sets container to null. In fact, all the methods I've tried from myView.ItemContainerGenerator returns null.
So, how should I go about attaching my event handler, so that I can respond to the buttons being clicked?
I have not done any Windows 7 Phone development, but I have done plenty of XAML + Silverlight development with C# and now I'm getting into doing some F# development. The approach I would take is by not using event handler's at all. Since you are using a button, make a class that derives from ICommand and add that type as a public property on your ViewModel so you could bind it to the Command property of the button. The benefits of using the ICommand interface over event handlers is that you could also have a condition on when the button is enabled to do the action.
Also, take notice that when you are doing binding expressions within (i.e. ItemTemplate) items in an ItemsControl control, the scope of what properties you can bind to are reduced to the properties of the current item. So all of the properties of the ViewModel are out of scope, unless you specify it fully i.e. <Button Command={Binding Source=ViewModel, Path=Property1.Property2.etc} />. Let me know if this helped.

eventocommand not working

I am making one application in MVVM using Galasoft MVVM Light toolkit. However i can't make EventToCommand make it work with Telerik Context Menu. Here is my code :-
<ListBox x:Name="lstPhotoAlbums" ItemsSource="{Binding AlbumsCollection}"
Margin="3,0" Grid.Row="1" ItemsPanel="{StaticResource wrapPanelItemsPanelTemplate}"
ItemTemplate="{StaticResource ListboxPhotosDataTemplate}"
ItemContainerStyle="{StaticResource ListboxPhotoAlbumsContainerStyle}" Height="500" HorizontalAlignment="Left" VerticalAlignment="Top" Width="178">
<telerik:RadContextMenu.ContextMenu>
<telerik:RadContextMenu x:Name="albumsCtxMenu">
<telerik:RadMenuItem Header="Delete" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding DeleteAlbumCommand}" CommandParameter="{Binding SelectedItem, ElementName=lstPhotoAlbums}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</telerik:RadMenuItem>
</telerik:RadContextMenu>
</telerik:RadContextMenu.ContextMenu>
</ListBox>
I do hit the breakpoint in my viewmodel. However the command parameter is always null. Any ideas where i am wrong?
Thanks in advance :)
As this is an old post, you might have found the answer to your question. However, as I was trying to do the same, I did not find a precis answer to this and if others are looking for the same, I hope this might help them.
You will need to remove the CommandParameter argument from your EventToCommand and change it to this:
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding DeleteAlbumCommand}" PassEventArgsToCommand="True" />
Your RelayCommand in your ViewModel or whereever you are implementing your RelayCommand would have to look something like this:
RelayCommand<EventArgs> DeleteAlbumCommand = new RelayCommand<EventArgs>(CallbackMethod);
CallbackMethod should then look something like this:
private void CallbackMethod(EventArgs eventArgs)
{
...
}
Hope this will help.