|
i'm indebted with this other book:
Pro WPF in .NET 4 - by Matthew MacDonald (Apress)[^]
the source code for this book is also available there.
what you will get?:
.every major WPF feature
.useful source code examples (accessible enough to understand quickly)
|
|
|
|
|
I can only read one at a time. but Thank You. It's hard to pass up on the heavy endorsements from all the article writers here on code project.
If I still need help after reading it I will buy that one also.
Frazzle the name say's it all
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
John F. Woods
|
|
|
|
|
Ok, so I have my tab style working. The tabs now show the text and a close button. Here's my style:
<Style TargetType="{x:Type TabItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate >
<Grid HorizontalAlignment="Stretch" Height="22">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2" ></RowDefinition>
<RowDefinition Height="Auto" ></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="1" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem} }, Path=Header}"
VerticalAlignment="Bottom" Margin="4,0,8,0"/>
<Button Grid.Row="1"
Grid.Column="1"
Height="16"
Width="16"
BorderBrush="{x:Null}" Background="{x:Null}"
Foreground="#FF224A71"
VerticalAlignment="Center"
Padding="3,0"
Command="{Binding CloseTabCommand}">
<TextBlock Text="x"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="0,0,0,2"/>
<Button.ToolTip>
<controls:ToolTipEx Style="{StaticResource TooltipStyle}"
HeaderText="Close"
Icon="/FMG.UI.WPF;component/Media/Images/home_16.png"
ContentAreaText="Closes this tab"/>
</Button.ToolTip>
<Button.OpacityMask>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#4BFFFFFF" Offset="1"/>
</LinearGradientBrush>
</Button.OpacityMask>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<!--<Controls:CloseTabbedViewAction />-->
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
You can see the button is bound to a CloseTabCommand.
When I run it, the command isn't fired. Here's the command from the VM:
private ICommand _CloseTabCommand;
public ICommand CloseTabCommand
{
get
{
if (_CloseTabCommand == null)
_CloseTabCommand = new RelayCommand(p => closeTabExecuted(), p => closeTabCanExecute());
return _CloseTabCommand;
}
}
What am I doing wrong?
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
As this is inside a template, you aren't getting the DataContext . The easiest way to solve this is to use FindAncestor to find the TabItem that this belongs to and get the DataContext from that.
|
|
|
|
|
Ok, I see. I'm trying this but it's still not firing:
<Button Grid.Row="1"
Grid.Column="1"
Height="16"
Width="16"
BorderBrush="{x:Null}" Background="{x:Null}"
Foreground="#FF224A71"
VerticalAlignment="Center"
Padding="3,0"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}, Path=CloseTabCommand}"
>
If it's not broken, fix it until it is
|
|
|
|
|
You need to be looking for the TabItem, not the Button as an ancestor.
|
|
|
|
|
Ok, so now I have this:
<Button Grid.Row="1"
Grid.Column="1"
Height="16"
Width="16"
BorderBrush="{x:Null}"
Background="{x:Null}"
Foreground="#FF224A71"
VerticalAlignment="Center"
Padding="3,0"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=CloseTabCommand}">
It's still not workong. I have a context menu on the tab which includes Close and the command works from there, but not from this button.
If it's not broken, fix it until it is
|
|
|
|
|
The AncestorType should be the bound to the control that is in turn bound to the VM. In most cases this is the Window/UserControl and not really the particular control in that Window, if you get what I mean.
Say you have a Window with it's DataContext set to the ViewModel that contains the CloseTabCommand, then you would do this
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=CloseTabCommand}" .
Hope this helps
When I was a coder, we worked on algorithms. Today, we memorize APIs for countless libraries — those libraries have the algorithms - Eric Allman
|
|
|
|
|
It still doesn't know about the DataContext though. To fix this, replace it with this:
<Button Grid.Row="1"
Grid.Column="1"
Height="16"
Width="16"
BorderBrush="{x:Null}" Background="{x:Null}"
Foreground="#FF224A71"
VerticalAlignment="Center"
Padding="3,0"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type TabItem}}, Path=DataContext.CloseTabCommand}">
|
|
|
|
|
Thanks Pete. That did it!! +5
If it's not broken, fix it until it is
|
|
|
|
|
|
Yes I am. Learning is a team sport.
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
I'm trying to style a tab item like this[^].
So I copied this style into my view, but I don't understand how to apply this. Where/how in the TabControl XAML do I use this?
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
Put it into a Resources section and drop the x:Key part to have it automatically applied to the TabItem elements.
|
|
|
|
|
Ok, so that sorta worked. I get the button, but not the header text
If it's not broken, fix it until it is
|
|
|
|
|
[UPDATE] Found it..
I have a listbox with hyperlinks as the list items. But the selected item is a blue bar with white text. I'd like to remove the highlighting. Here's what I have so far:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="..\Resources.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<Trigger Property="IsMouseCaptureWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
<DataTemplate DataType="{x:Type models:JobModel}">
<StackPanel Orientation="Horizontal"
Margin="2">
<Image Source="/FMG.UI.WPF;component/Media/Images/job_72.png"
Height="16"
Width="16"
Margin="0,0,3,0"/>
<controls:TextBlockEx>
<Hyperlink Style="{StaticResource linkStyle}"
Command="{Binding SelectedJob, Mode=TwoWay}">
<TextBlock Text="{Binding JobNumber}"/>
</Hyperlink>
</controls:TextBlockEx>
</StackPanel>
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
and
<ListBox Grid.Row="1"
Grid.Column="0"
ItemsSource="{Binding Jobs}"
SelectedItem="{Binding SelectedJob}"
BorderThickness="1"
BorderBrush="#6593CF"
Margin="-1,0,-1,-1">
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Background" Value="Transparent"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.Resources>
</ListBox>
Can someone show me how to remove the selected item's fore & back color so it ddoesn't appear selected?
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
<pre lang="text">
1.How to bind the MenuItem Command of ListBoxItem ContextMenu dynamically?
2. How to set its CommandParameter?
//----------------------------------
//MainWindowView.xaml
//----------------------------------
<Window x:Class="MVVM.Views.MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:vm="clr-namespace:MVVM.ViewModels"
Title="MainView" Height="354" Width="520">
<Window.DataContext>
<vm:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<!--In this ListBox, the MenuItem command can not be called-->
<ListBox Height="252" HorizontalAlignment="Left" Margin="12,51,0,0" Name="listBox1" VerticalAlignment="Top" Width="201"
ItemsSource="{Binding Path=TestItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Width="150">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Call Command1" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Command1}" CommandParameter="???"/><!--here the Command1 not be called-->
</i:EventTrigger> <!--how to set command parameter to this ListBoxItem displaying text?-->
</i:Interaction.Triggers>
</MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!--In this ListBox, the menuitem command can be called,
but the command parameter can not be set correctly-->
<ListBox Height="252" HorizontalAlignment="Left" Margin="230,51,0,0" Name="listBox2" VerticalAlignment="Top" Width="229"
SelectedItem="{Binding SelectedText,Mode=OneWayToSource}">
<ListBoxItem>
<TextBlock Text="item1" Name="tb" />
<ListBoxItem.ContextMenu>
<ContextMenu>
<MenuItem Header="Call Comand1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<!--this one can be called correctly,
but the command parameter can not be set correctly-->
<i:InvokeCommandAction Command="{Binding Command1}" CommandParameter="{Binding ElementName=tb,Path=Text}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</MenuItem>
</ContextMenu>
</ListBoxItem.ContextMenu>
</ListBoxItem>
<ListBoxItem>
<TextBlock Text="item2"/>
<ListBoxItem.ContextMenu>
<ContextMenu>
<MenuItem Header="Call Comand1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Command1}" CommandParameter="" />
</i:EventTrigger>
</i:Interaction.Triggers>
</MenuItem>
</ContextMenu>
</ListBoxItem.ContextMenu>
</ListBoxItem>
</ListBox>
<Label Content="This one can not work" Height="28" HorizontalAlignment="Left" Margin="12,25,0,0" Name="label1" VerticalAlignment="Top" />
<Label Content="This one can work" Height="28" HorizontalAlignment="Left" Margin="230,25,0,0" Name="label2" VerticalAlignment="Top" />
<Label Content="Test ListBox ContextMenu" Height="28" HorizontalAlignment="Left" Margin="12,0,0,0" Name="label3" VerticalAlignment="Top" />
</Grid>
</Window>
//------------------
//MainWindowViewModel.cs
//---------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows;
using System.Windows.Controls;
using MVVM.Command;
namespace MVVM.ViewModels
{
public class MainWindowViewModel : ViewModelBase
{
public List<string> TestItems
{
get
{
return new List<string>()
{
"Item1",
"Item2",
"Item3"
};
}
}
public ListBoxItem SelectedText
{
get;
set;
}
public MainWindowViewModel()
{
}
private ICommand _command1;
public ICommand Command1
{
get
{
if(null==_command1)
{
_command1 = new DelegateCommand<string>((str) =>
{
MessageBox.Show("Command1 with parameter:" + str+((TextBlock)SelectedText.Content).Text);
});
}
return _command1;
}
}
ICommand _command2;
public ICommand Command2
{
get
{
if (null == _command2)
{
_command2 = new DelegateCommand<Button>((button) =>
{
if (null == button)
return;
Point p = Mouse.GetPosition(button);
button.Content = string.Format("{0},{1}", p.X, p.Y);
});
}
return _command2;
}
}
}
}
</pre>
|
|
|
|
|
You have to either bind it to a property in your list item object, or to a static property or hard code it. In your case, you can also just specify "{Binding}" in the command parameter and it will pass in the actual object.
|
|
|
|
|
Thank you very much, SledgeHammer01.
My issue is the ListBox1 MenuItem Command binded in ListBoxItem ContextMenu MenuItem does not work. But MenuItem Command in ListBox2 can work well.
I don't know why. In my project, I need dynamically bind the menu itms just like in ListBox1 used.
Could you please help check it? thanks a lot.
|
|
|
|
|
Oh... I see what you are asking. Yeah, you're doing it wrong in both cases. You should use the ItemsSource property of the listbox to set the collection of items. There is no need to use the ItemTemplate if all you are doing is showing a TextBlock as that is the default behavior. You should specify the context menu on the ListBoxItem, not the TextBlock. Then you can use {Binding} to pass in the item itself, but it will not be necessary as the sender will be the item.
|
|
|
|
|
Thanks a lot.
I'm newer for WPF binding. I tried and tried again. And the MenuItem command in listbox1 still can not be fired.
|
|
|
|
|
Well, post your corrected code.
|
|
|
|
|
Do you have email? I can send you my demo version to you. Thanks a lot.
my email is neighbornet@163.com
|
|
|
|
|
how do we use expression blend???? can you send me some sample programms using expression blend????
aishu
|
|
|
|
|
"mm" is not a very good title for a question; try putting something meaningful. As to Expression Blend, follow the link I gave you in your other question and find it in MSDN.
One of these days I'm going to think of a really clever signature.
|
|
|
|