WPF: Need a nearly "invisible" TabControl. What do I need to override? - wpf

For my application, I need a TabControl which will host 2 DataGrids. The control must be as unobtrusive as possible: only the tabs should be seen.
I am told that the solution is somewhere here:
http://msdn.microsoft.com/en-us/library/ms754137.aspx
I guess that I will have to change some value(s) to zero (maybe negative?)
Can you folks provide details?
TIA

I think it's much easier to use a RadioButton than a TabControl
<StackPanel Orientation="Horizontal">
<RadioButton Name="tab1" Content="Tab 1" />
<RadioButton Name="tab2" Content="Tab 2" />
</StackPanel>
<DataGrid>
<DataGrid.Visibility>
<Binding ElementName="tab1" Path="IsChecked">
<Binding.Converter>
<BooleanToVisibilityConverter />
</Binding.Converter>
</Binding>
</DataGrid.Visibility>
</DataGrid>
<DataGrid>
<DataGrid.Visibility>
<Binding ElementName="tab2" Path="IsChecked">
<Binding.Converter>
<BooleanToVisibilityConverter />
</Binding.Converter>
</Binding>
</DataGrid.Visibility>
</DataGrid>

Related

Hide/Show DataGrid based on Selected ListBoxItem in WPF

I have a ListBox:
<ListBox Name="ListB" SelectedIndex="0" ItemsSource="{Binding Account}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock FontSize="16" Grid.Column="0" Grid.RowSpan="3">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}" >
<Binding Path="AccountNumber" />
<Binding Path="Name" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Based on the AccountNumber I want to Show/Hide DataGrid's that are bound to the ListBoxItems:
<!--DataGrid 1-->
<DataGrid ItemsSource="{Binding ElementName=ListB, Path=SelectedItem}">
..................
</DataGrid>
<!--DataGrid 2-->
<DataGrid ItemsSource="{Binding ElementName=ListB, Path=SelectedItem}">
..................
</DataGrid>
Is there any if/else in WPF? For example
if SelectedItem in ListBox has an AccountNumber 100
than show DataGrid 1 and hide DataGrid 2
else hide DataGrid 1 and show DataGrid 2.
Thank you in advance for the tips.
Unfortunately WPF does not come with if/then/else structures. You have to build up a work-arround or use frameworks, which can solve your issue. One possible solution is to use blend sdk's interaction trigger framework:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
The behavior you mention would be implemented as following:
<i:Interaction.Triggers>
<!-- One Trigger for equal 100 -->
<ei:DataTrigger Binding="{Binding Path=SelectedItem.AccountNumber,
ElementName=ListB}"
Value="100">
<ei:ChangePropertyAction TargetName="DataGrid1"
PropertyName="Visibility"
Value="Collapsed" />
<ei:ChangePropertyAction TargetName="DataGrid2"
PropertyName="Visibility"
Value="Visible" />
</ei:DataTrigger>
<!-- One Trigger for not equal 100 -->
<ei:DataTrigger Binding="{Binding Path=SelectedItem.AccountNumber,
ElementName=ListB}"
Comparison="NotEqual"
Value="100">
<ei:ChangePropertyAction TargetName="DataGrid1"
PropertyName="Visibility"
Value="Visible" />
<ei:ChangePropertyAction TargetName="DataGrid2"
PropertyName="Visibility"
Value="Collapsed" />
</ei:DataTrigger>
</i:Interaction.Triggers>
You will need to include System.Windows.Interactivity.dll into your project references.
Also required would be Microsoft.Expression.Interactions.dll
Another solution would be to bind the visibility of your DataGrids directly to SelectedItem.AccountNumber and attach and IValueConverter, which extracts the Visibility according to logic.
Using the SelectionChanged Event of the ListBox would also work, but becomes pretty much unreadable and may be redundant. If you follow the MVVM approach, your code behind should be almost empty.
This would be straightforward if you were using a MVVM framework.
Add a BooleanToVisibility converter to your View as in this example, with boolean properties to control the visibility of each grid in the ViewModel which are updated whenever the ListBox.SelectedItem is changed.

Binding Row to Validation Rule WPF

I want to bind TextBox's Tag (which is inside a DataGrid), to validation rule's CurrentLegStrategy property (which is a DependencyProperty). Although I've done something similar with Deal dependency property using a global tunnel object, however not able to figure out, what would be the tunnel for CurrentLegStrategy (ideally should be coming from the bound data to DataRow or to the bound data to TextBox's tag)?
<DataTemplate x:Key="PremiumProp">
<TextBlock Style="{StaticResource TextBlockLeft}" Tag="{Binding Strategy}" x:Name="txtPremiumProp">
<TextBlock.Text>
<Binding Path="AbsolutePremium" StringFormat="{}{0:#,##0.00####}" Converter="{StaticResource _DoubleConvertor}">
<Binding.ValidationRules>
<Control:MBSStrategyBasedDoubleValidation ValidatesOnTargetUpdated="True" ValidationTag="premabs"
ErrorMessage="Please enter a valid positive (+) premium (also check the reference which is required for auto calculation)!">
<Control:MBSStrategyBasedDoubleValidation.Deal>
<Control:DealObject Deal="{Binding Tag, Source={StaticResource TradeTunnel}}" CurrentLegStrategy="{Binding Path=Tag, ElementName=txtPremiumProp}"/>
</Control:MBSStrategyBasedDoubleValidation.Deal>
</Control:MBSStrategyBasedDoubleValidation>
</Binding.ValidationRules>
</Binding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
Then I also tried,
<TextBlock.Resources>
<ResourceDictionary>
<FrameworkElement x:Name="strategySource" Tag="{Binding Tag, Source={x:Reference txtPremiumProp}}"/>
</ResourceDictionary>
</TextBlock.Resources>
With the following:
CurrentLegStrategy="{Binding Path=Tag, Source={StaticResource strategySource}}"
Cannot find resource named 'strategySource'. Resource names are case sensitive.

WPF Object send itself as MultiBinding path

Basically what I need to know is how to send the source of an HierarchicalDataTemplate into a binding, this is what I have:
<HierarchicalDataTemplate DataType="{x:Type myModel:Person}">
<StackPanel Orientation="Horizontal">
<Image Source="Images\User.gif" />
<TextBlock Margin="5,0,0,0" Text="{Binding Name}" />
</StackPanel>
<HierarchicalDataTemplate.ItemsSource>
<MultiBinding Converter="{StaticResource PersonConverter}">
<Binding Path="Name" />
<!-- Here I need something like Binding Path="Self" so I can send the source of the binding (the "Person" object) -->
</MultiBinding>
</HierarchicalDataTemplate.ItemsSource>
</HierarchicalDataTemplate>
So my source is an object of type myModel:Person, I want to be able to send the object itself in the MultiBinding so the PersonConverter can use it.
Thanks for any help.
Wow, I did a crazy wild guess and it worked =S lol, here's the solution
<MultiBinding Converter="{StaticResource PersonConverter}">
<Binding Path="Name" />
<Binding Path="." /> <!-- this sends the source of the binding -->
</MultiBinding>
Thanks!

WPF Commands Buttons ListBoxItems

I Have a listbox defined like below :
<ListBox x:Name="lstMedias" ItemsSource="{Binding Medias}" Width="Auto" Height="Auto">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}" Tag="{Binding Name}" Click="Button_Click" Command="{Binding Path=LoadSimpleMoviePopupCommand}">
<Button.Resources>
<Converters:LoadMovieMultiConverter x:Key="LoadMovieMultiConverter" />
</Button.Resources>
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource LoadMovieMultiConverter}">
<MultiBinding.Bindings>
<Binding ElementName="DragDropCanvas" />
<Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
</MultiBinding.Bindings>
</MultiBinding>
</Button.CommandParameter>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
When Trying to call command LoadSimpleMoviePopupCommand, command is not called, but when calling click event, event is raised.
Do You have an idea why ? It is a normal behavior ? Do we have to trick like ListBoxItem doubleclick ?
Probably because the binding failed. Check the output window of VS and see if there are any binding errors. I suspect the LoadSimpleMoviePopupCommand property is not on your data item class (ie. your Media class).
had the same problem, try this
<Button Command="{Binding DataContext.YourCommand,RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
it's quite normal, he can't find your command binding inside the listbox because you set something like
<DataTemplate DataType ...
in that listbox so he'll be looking for that binding inside the datatype and not the viewmodel (I assume :)

XAML - Binding to DataContext and using converter?

To bind to the current DataContext in XAML you can use:
<TextBlock Text="{Binding}" />
How do you do this using a converter in the mix?
The following works when you have a property on the path:
<TextBlock Text="{Binding MyProperty,Converter={StaticResource converter}}" />
But I dont want to do that; I just want to Bind to the datacontext and not the datacontext.MyProperty if you get what I mean.
Simply omit the path:
<TextBlock Text="{Binding Converter={StaticResource converter}}" />
Ah wait - I notice your question is tagged with Silverlight. Does this not work in Silverlight? If not, you may need to use the expanded syntax:
<TextBlock>
<TextBlock.Text>
<Binding Converter="{StaticResource converter}" />
</TextBlock.Text>
</TextBlock>
Dot sign also provide DataContext Binding for SL developers
<TextBlock Text="{Binding Path=.,Converter={StaticResource converter}}" />

Resources