|
Pete O'Hanlon wrote:
So, what is an attached event? Well, basically, it's an event that can be attached to another element without the other element having to be aware that this capability is present. If you think about it as being like an attached property for events then it starts to make sense. So, why do we have this? Well, it allows you to extend WPF through composition rather than inheritance.
I understand perfect "Grid.Row" is an "Attached Property" that it's not a property of "TextBox" itself for instance. I understand analogy when this concept extended to "Events". However - what's confusing is the SYNTAX: you can define an event handler to a RoutedEvent the same way/syntax as you would with AttachedEvent.
But if you see the sample I gave in MainWindow.xaml, I can subscribe to "AttachedEvent" and "RoutedEvent" from xaml in same syntax - the syntax which does not require "Instance" of "GrandChild" (i.e. "MainWindow" does NOT implement event GrandChildRoutedEvClick itself, which is declared in "GrandChild")
From MainWindow.xaml, "RoutedEvent" handler setup like this:
<br />
local:GrandChild.GrandChildRoutedEvClick="GrandChild_GrandChildRoutedEvClick"<br />
From MainWindow.xaml, "AttachedEvent" handler setup like this:
<br />
local:GrandChild.GrandChildAttachedEvClick="GrandChildAttachedEvClickHandler" <br />
Despite in "MiddleChild.xaml", I setup handler to "RoutedEvent" the "Propery way"... what's real diff between Routed/AttachedEvent besides phylosophical or syntactical ...?
<br />
[local:GrandChild x:Name="Junior" VerticalAlignment="Stretch" GrandChildRoutedEvClick="GrandChild_GrandChildRoutedEvClick"/]<br />
What I am saying is, you can define a DockStateChanged event with syntax of a "RoutedEvent" - not "AttachedEvent", and in some parent control couple layers up, setup event handler using syntax as you would consuming an "AttachedEvent"
dev
modified 30-Jan-13 5:11am.
|
|
|
|
|
As I said. An attached event is a specialist form of routed event. I don't know how I can say it any clearer - other than an attached event IS A routed event that is used for a specific purpose that routed events aren't designed for.
|
|
|
|
|
|
Don't mention it. I hope it's clearer now.
|
|
|
|
|
I heard ya, I was looking for some sort of confirmation.
dev
|
|
|
|
|
I created a tab stle so that it has a close button. The button is bound to a command:
<Style TargetType="{x:Type TabItem}">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Close"
Command="{Binding CloseTabCommand}"/>
<MenuItem Header="Close All But This"
Command="{Binding CloseAllOtherTabsCommand}"/>
<MenuItem Header="Float"
Command="{Binding FloatTabCommand}"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
I tried this:
<MenuItem Header="Close"
Command="{Binding CloseTabCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabItem}}}"/>
but I get null passed to the command.
I need to pass along a reference to the tab. Can someone show me how to get the tab in this style and pass it as a parameter?
Thank you
If it's not broken, fix it until it is
modified 30-Jan-13 0:12am.
|
|
|
|
|
You won't find the TabItem like that because the ContextMenu is a pop up window and thus is in a different visual tree.
Do this instead:
{Binding Path=PlacementTarget, RelativeSource={RelativeSource
AncestorType=ContextMenu}}
|
|
|
|
|
Ok, I finally got around to this again. So now I'm trying this:
<Style TargetType="{x:Type TabItem}">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Close"
Command="{Binding CloseTabCommand}"
CommandParameter="{Binding Path=PlacementTarget, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
</Setter.Value>
</Setter>
Here's my command:
private ICommand _CloseTabCommand;
public ICommand CloseTabCommand
{
get
{
if (_CloseTabCommand == null)
_CloseTabCommand = new RelayCommand<object>(p => closeTabExecuted(p), p => closeTabCanExecute(p));
return _CloseTabCommand;
}
}
and the methods:
private bool closeTabCanExecute(object obj)
{
return true;
}
private void closeTabExecuted(object obj)
{
TabManager.CloseActiveTab();
}
Again, the command fires but null is passed to closeTabExecuted.
I'm stuck here. Could use some more help.
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
Works all day long for me. I copy & pasted your code and got the TabItem in both closeTabExecuted and closeTabCanExecute. Are you sure your RelayCommandT is not broken?
|
|
|
|
|
I am new to WPF applications. I come from a VB6 Windows Forms background. I used to create user controls that I used in UI's to create graphic content controls like buttons with normal, down,and hover images. While I know the ultimate way to do this is create a separate project for my custom controls I am just working withing a single project to get things worked out first.
I have created a Controls folder where I have added several custom controls each inherting from a base control like Button, RadioButton, Slider, Checkbox etc. I can then add properties to each custom control for DefaultImage, DownImage, HoverImage and in the case of a Slider GripImage and GutterImage. The properties have a public set/get property so I can set the images for a specific control and then the control behavior can set the proper image.
There is an Images folder where I put all the images needed for the application.
I have created a Images.xaml ResourceDictionary that defines key names like ButtonDown to the specific image names so the image naming in the template is easier and I can swap out images easily.
A Generic.xaml gets created in the Themes folder where the basic Control Template goes. Not sure if this is best practice for storing each Control Template or not but it is what gets created by default.
My main area of difficulty is creating the template. I know what I want to do but can't get the syntax to work correctly.
In the case of the custom button I want to create triggers for IsPressed and IsMouseOver and set the controls Background ImageBrush to the proper image. When those triggers are false I want to set the background image to the DefaultImage
I'm not sure about the syntax for refering to the image property of the custom Control and how best to access it in the xamal.
I've looked at a lot of examples but none seem to do things the way I am organizing it. I don't want to hard code the images to the control. My ultimate goal is to be able to drag the custom control into a grid using the designer and set the Default, Down, and Hover image properties and then place the control how I want it in the designer. Then if I want to change the entire look of the app I can just swap out images in the Images folder and the GUI will change.
|
|
|
|
|
For starters, you should only use images when its actually an image. For other cases, you should draw the part using XAML primitives. In the example you mentioned, the slider thumb and gutter and tick marks, etc. should all be drawn in XAML primitives. You'll find out why down the road .
When you are inheriting from a system control, you should generally NOT write your own template from scratch, but rather dump out the Microsoft template and either inherit from it, or paste it into your assembly and modify it. Reason being is that while Microsoft pushes "lookless" controls (the XAML has no knowledge of the code and the code has no knowledge of the XAML), you'll find out they are not. Controls often rely on primitives being in certain layouts and having certain names.
Dumping out the Microsoft templates is also a GREAT way to teach you how real world controls are put together.
I typically use Expression Blend for dumping out templates.
NOTE: unless you are going to have a control that is themeless, you need to do a lot of tricks to have say an XP theme, an Aero theme, Green theme, Blue Theme,etc. so you respect the users settings. If you are just going to have one look & feel across all themes / OS'es, etc. then you don't need to worry about that as much.
Just follow the Microsoft template lead to be honest with you... they are doing it "the right way".
|
|
|
|
|
I should probably point out that the UI's that I build are VERY graphic in nature with borderless nonsizeable main windows with irregular shaped graphic backgrounds. All Buttons, radios, checkboxes, sliders and other basic controls are designed by a graphic designer and then sliced up for the GUI. These are NOT standard UI's. The GUI's are used for small utility setting setup (think tooltray app for setting up some small feature) or they are internal tools that are used by non computer people or used as a demo on a large screen or demo room with specific hardware to demonstrate a feature.
That said...how do I "Dump out" a control template?
|
|
|
|
|
Yeah, I get it. As I said in my original response, that is how you did it in Win32 / MFC / Winforms, etc. If you are going to do WPF, you should use the WPF mechanisms. Otherwise, why bother? Not trying to be a dick, just saying lol... If you are not going to do that... might as well stick with Winforms, as you won't get any of the WPF advantages.
You will be surprised what can be drawn with WPF primitives... there's a guy on here who is a REAL stud at that...
[^]
[^]
[^]
are just some examples.
download a copy of Expression Blend (a Microsoft app) and you can drag a control on a form, right click and dump out the template. You'll get full compilable XAML, all the brushes, resources, etc.
You'll notice EVERYTHING... buttons, checkboxes, radio buttons, etc. are all drawn with XAML.
Honestly, if you are working with a photoshop graphic designer (traditional), you might as well skip WPF as you'll just be piecing together all the graphics Winform style anyways. You really need a designer that knows the WPF tools (Expression Blend, Sketch Flow, etc). Should not be too hard for a photoshop guy to learn Expression Blend (if he is interested) as it pretty much works the same way... drop primitives like lines, curves, gradients, etc. on the form and do stuff.
You ***WILL*** need to draw ***EVERYTHING*** using XAML primitives if you want to do the fancy WPF stuff... animations, fading, special fx, etc.
|
|
|
|
|
how can change selected node in treeview with mouse right click without writing handler in code behind.
|
|
|
|
|
I'm stuck here guys. I could really use another pair of eyes on this.
I have a treeview. It's bound to an ObservableCollection<treenode> called Nodes. The bound data on the tool tips is not showing:
<controls:TreeViewEx BorderThickness="0"
ItemsSource="{Binding Nodes}"
SelectedItemEx="{Binding SelectedTreeNode, Mode=TwoWay}">
<controls:TreeViewEx.ToolTip>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Row="0"
Grid.Column="0"
Source="/FMG.UI.WPF;component/Media/Images/job_128.png"
Height="16"
Width="16"/>
<TextBox Grid.Row="0"
Grid.Column="1"
Text="Job: "
FontWeight="Bold"/>
<TextBox Grid.Row="0"
Grid.Column="2"
Text="{Binding ToolTipHeader}"/>
<Border Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="3"
Height="2"
BorderBrush="Gray"/>
<TextBox Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="3"
Text="{Binding ToolTipDetails}"/>
</Grid>
</controls:TreeViewEx.ToolTip>
</controls:TreeViewEx>
The tooltip pops up, but the ToolTipHeader and and ToolTipDetails are blank. The Output window says it can't find them on the view model. How do I make the binding look on the Node, not the view model?
Thanks
If it's not broken, fix it until it is
modified 28-Jan-13 23:04pm.
|
|
|
|
|
Hi Kevin,
what is the DataContext of the ToolTip?
Because the bindings look at e.g. DataContext.ToolTipHeader .
Have a look at what Karl Shifflett did here: http://karlshifflett.wordpress.com/2007/12/29/wpf-sample-series-data-binding-in-tooltip/[^]
If you change <controls:TreeViewEx.ToolTip> to:
<controls:TreeViewEx.ToolTip>
<ToolTip DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
<Grid></Grid>
</ToolTip>
</controls:TreeViewEx.ToolTip>
And change the binding of the textbox to e.g. Text="{Binding SelectedItemEx.ToolTipHeader}"
then it should work, if SelectedItemEx has the property ToolTipHeader .
But you realize that you define a tooltip for the whole treeview control and not for each treeview node, right?
Of course, if the tooltip has already as datacontext your viewmodel then Text="{Binding SelectedTreeNode.ToolTipHeader}"
should work too (without setting the ToolTip DatContext=...) stuff.
Bye,
Thomas.
|
|
|
|
|
Hello!
I have a treeview:
<TreeView
BorderBrush="Black"
BorderThickness="2"
Cursor="Hand"
ItemsSource="{Binding Data, UpdateSourceTrigger=PropertyChanged}" >
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter
Property="IsSelected"
Value="{Binding SelectedPath, Mode=TwoWay}" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate
ItemsSource="{
Binding Persons,
UpdateSourceTrigger=PropertyChanged}"
DataType="{x:Type local:Data}" >
<Grid>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="dane" Text="{Binding ID}" Margin="0,0,5,0" />
<Button
Style="{StaticResource ButtonLikeTextBlock}"
Content="{Binding DataOrName}"
Command="
{Binding
Path=DataContext.DisplayInfoCommand,
RelativeSource = {RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
</StackPanel>
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
How can i get the ID property which is in Persons list ? How can i bind it straight to viewmodel class? Can u show sample code?
Greetings, Boryborawski.
|
|
|
|
|
Hello,
I'm building WPF(MDI) application.
I want my main window to have some constant header and footer(like in a browser) and the area between the header and the footer will change dynamically.
I googled but didn't find any thing useful, can someone help on this one?
Thanks
|
|
|
|
|
|
Hello,
I'm using WPF.MDI.dll assembly in my project.
This is my Main window XAML file:
<Window x:Class="PL.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mdi="clr-namespace:WPF.MDI;assembly=WPF.MDI"
Title="MainWindow" Height="400" Width="800">
<DockPanel>
<mdi:MdiContainer>
</mdi:MdiContainer>
</DockPanel>
</Window>
As soon as i added the lines:
<mdi:MdiContainer>
</mdi:MdiContainer>
I got the next message at the designer:
System.NullReferenceException<br />
Object reference not set to an instance of an object.<br />
at WPF.MDI.MdiContainer.MdiContainer_Loaded(Object sender, RoutedEventArgs e)<br />
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)<br />
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)<br />
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)<br />
at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)<br />
at System.Windows.BroadcastEventHelper.BroadcastEvent(DependencyObject root, RoutedEvent routedEvent)<br />
at System.Windows.BroadcastEventHelper.BroadcastLoadedEvent(Object root)<br />
at MS.Internal.LoadedOrUnloadedOperation.DoWork()<br />
at System.Windows.Media.MediaContext.FireLoadedPendingCallbacks()<br />
at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()<br />
at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)<br />
at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)<br />
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)<br />
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
Any body can help me solve the problem?
Thanks!!!
|
|
|
|
|
|
Hey,
I copy pasted this example and still i get the error...
|
|
|
|
|
check your dll assembly.
I implemented it tonight and found no error.
--AP
|
|
|
|
|
hai am also getting same error have you found any solution..?
|
|
|
|
|
I have a application that has a page that receives multiple packets from a TCP/IP server. Every time it receives it tries to run an event using Dispatcher.BeginInvoke which runs the event. The problem is that the event only runs on the first time Dispatcher.BeginInvoke. I believe that the reason for this is that because the thread is already running it can not be started again. Also, I have tried the Backgroundworker class and as soon as it hits my code I get an "Invalid cross thread access" error which makes me put the code back into the Silverlight Dispatcher.BeginInvoke and the origional problem occurs. How do I fix my problem?
Thanks,
Steve Holdorf
-- modified 25-Jan-13 7:06am.
|
|
|
|
|