I have a project created in C# in Visual Studio 2013 Express, a WPF application. when run with the debugger from Visual Studio, the application Window appears the correct size, but when running the same generated executable from the bin folder, the window is about 5-7px taller. It's worth mentioning that the Window.Height is controlled dynamically by the underlying code.
That said, why does the size differ during runtime like it does? I'm new to development on Windows.
Here's my code that does the resizing:
const int WindowBaseHeight = 94;
const int ItemHeight = 68;
ObservableCollection<obj> CurrentItems = new ObservableCollection<obj>();
AppWindow.Height = WindowBaseHeight + ItemHeight * CurrentItems.Count;
Ok. Take a deep breath, then delete your code and start all over.
First of all, if you're working with WPF, you need to leave behind any and all approaches you might be used to from other technologies and understand and embrace The WPF Mentality.
Basically, you never need to do any manipulations of layout, nor manual resizing of UI elements, nor anything like that in procedural code, because WPF is Resolution Independent by default and it provides several mechanisms to create auto-adjustable layouts and UIs that fit perfectly regardless of the available screen/window size.
In order to make the Window auto-size itself to it's contents' size, you must set the Window.SizeToContent property accordingly.
Another very important aspect that you need to understand is that in WPF, any UI that shows "items" (any UI that shows 2 or more of the same "thing", regardless what the "thing" is) should be implemented using an ItemsControl.
This is how you create an auto-adjustable items-based UI in WPF where the items have a height of 68:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" SizeToContent="Height" Width="200">
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Height="68" Background="LightCyan">
<TextBlock Text="{Binding}"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
Code behind (for the sake of the example):
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = Enumerable.Range(0, 4).Select(x => "Item" + x.ToString());
}
}
Result:
Notice how I'm using the ItemsControl and DataBinding it's ItemsSource property in order to declaratively define the UI in proper XAML instead of procedurally creating the UI in code. This is the preferred approach in WPF for everything.
This approach reduces code behind to practically zero. As you can see in my example, all I'm doing is setting the DataContext of the Window to a relevant piece of data that can be used for DataBinding.
Also notice that there is no code whatsoever doing any manipulations of the UI. The Window size is set by WPF according to the value of the SizeToContent property, which is set to Height.
I'm binding to a List<string>, for the sake of the example, but you can databind to any types of .Net objects in WPF, and even directly to XML.
WPF Rocks. - Simply copy and paste my code in a File -> New Project -> WPF Application and see the results for yourself.
I suggest you read the linked material in this post, most importantly the "WPF Mentality" post, the DataBinding Overview, and the ItemsControl series. Let me know if you need further help.
Related
I have a working application that has been written in C#, and I now want to extend that application to allow the user to switch between viewing the application, and viewing a built in web browser (inside the same application window).
I also have a separate working web browser, that has also been written in C#.
I have just added the functionality to the original application to include 'tabbed' displays, where the original application will be displayed on the first tab, and a built in web browser on the second tab.
The 'tabbed' displays for the application have been created using XAML markup in Visual Studio. I now want to add an instance of the Web browser that has also been written in C# to the second tab that I have created in the XAML markup.
It would be something like:
<TabControl>
<TabItem Header="Browser">
<StackPanel>
<!-- Call/ instantiate the browser here -->
</StackPanel>
</TabItem>
</TabControl>
But I have no idea how I call/ create an instance of the browser from within the XAML markup...
The browser has been created using C#:
namespace Agent
{
public partial class Browser : Form
{
public Browser()
{
...
}
}
}
Can anyone explain to me how a create an instance of Browser inside the ` of the XAML markup?
Edit
Ok, so I have edited my XAML markup as recommended in the answer that's been suggested- I now have:
<Window ...
xmlns:Agent="clr-namespace:Agent"
...>
<Grid>
...
<TabControl>
<TabItem Header="R">
<StackPanel>
...
</StackPanel>
</TabItem>
<TabItem Header="Browser">
<Agent:Browser x:Name="Browser" />
</TabItem>
</TabControl>
</Grid>
</Window>
I have also updated my Browser.cs class, so that it is now extending UserControl, rather than Form:
public partial class Browser : UserControl{
However, I am getting a compile error on the line:
<Agent:Browser x:Name="Browser" />
which says:
The name "Browser" does not exist in the namespace "clr-namespace:Agent".
But clearly Browser does exist in Agent, as shown by the code I've included here... In fact, when typing the line <Agent:Browser x:Name="Browser />, when I typed the :, Browser was one of the options that came up in the autocomplete menu...
What am I doing wrong here? Why doesn't the compiler think that Browser exists inside Agent?
The key to instantiating any object in XAML is to make sure the namespace is declared. You can provide any XML prefix and assign it to your CLR namespace (ref) and it will act like a using statement. For example:
<TabControl xmlns:agent="clr-namespace:Agent">
<TabItem Header="Browser">
<StackPanel>
<agent:Browser/>
</StackPanel>
</TabItem>
</TabControl>
NOTE: your object has to extend UIElement (or one of its children) for it to work in a XAML tree. If your control is a WinForms control you either need to find the equivalent XAML control or wrap it in a WindowsFormsHost (ref).
WPF vs. WinForms
The purpose of this section is to help recognize which platform code is by namespace, as well as some of the trade-offs. I've used both and can say from experience that they each have good points and... not so good points.
WinForms classes live in the System.Windows.Forms namespace, and are available by referencing the System.Windows.Forms.dll assembly.
WPF classes live in the System.Windows and System.Windows.Controls namespaces, and are available by referencing a set of DLLs
WinForms rendering is immediate. That means you are working against bitmaps and you are responsible for clearing and redrawing stuff yourself (usually you can just call Invalidate()). If you do heavy image bit manipulation, WinForms is easier to work with.
WPF rendering is declarative. That means more work is offloaded to your GPU and you just tell it how to draw stuff. You can also use GPU render shaders for special effects. WPF has a nicer look out of the box, but it has a reputation for making easy things difficult but impossible things possible.
WinForms is easier to learn, but has a dated look out of the box.
WPF is built around data binding, enabling the UI to update in response to property values automatically. It's also able to be completely restyled, although that is quite an undertaking.
If you are just getting started, I'd go ahead and bite the bullet to start the heavier learning curve for WPF. It will provide a basic understanding that transfers to other platforms like Windows Store apps, etc.
Firstly you need to place that tag inside of your UserControl opening tag like so:
<UserControl x:Class="View.testControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:Agent="clr-namespace:Agent">
Then you can use it like this:
<TabControl>
<TabItem Header="R">
<StackPanel>
...
</StackPanel>
</TabItem>
<TabItem Header="Browser">
<Agent:Browser x:Name="Browser" />
</TabItem>
</TabControl>
EDIT
From what you told me in the comments you will need to create a Custom Control in your WPF project. To do that you need to:
Right Click your Project;
Select Add New Item;
From Installed (which is in the left column) select WPF;
From the list in the middle column select Custom Control;
Now you can create that control in your XAML with xmlns attribute.
Here is a great example from msdn on how to create custom controls
For example, I'd like to do something similar to what you see below, but in code behind. I see tons of example using XAML, but nothing for doing the same thing in C#. So my guess is no. Thanks.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBlock TextWrapping="Wrap" Width="455">
<Span FontSize="20">2</Span>
<Span BaselineAlignment="TextTop" FontSize="14">1/2</Span>
<Span FontSize="20"> + </Span>
<Span FontSize="20">3</Span>
<Span BaselineAlignment="TextTop" FontSize="14">3/4</Span>
<Span FontSize="20"> = </Span>
<Span FontSize="20">6</Span>
<Span BaselineAlignment="TextTop" FontSize="14">1/4</Span>
</TextBlock>
</StackPanel>
Yes, this XAML output can be done through C# code as well
Pseudocode
Create a StackPanel object
Create a TextBlock object. Set it's TextWrapping Property to Wrap and Width to 455.
Create multiple objects of Span. Set the FontSize and other properties (text, BaseAllighnemt) according to your needs.
Addspan objects to Textblock.Inlines property
Add Textblock to stackpanel
Thats it
Actually, almost anything that can be done in Xaml can be done in C# as well, since Xaml is converted into C# when building (look for *.g.cs files). You mostly can just use the same classes you specify in the Xaml, with a few additions that Xaml handles automatically for you. In this case you can do:
var textblock = new TextBlock();
textblock.Inlines.Add(new Run("2") {FontSize = 20});
textblock.Inlines.Add(new Run("1/2") {FontSize = 14, BaselineAlignment = BaselineAlignment.TextTop});
The XAML code is parsed and objects are created that correspond to the markup, so you can always do the same by creating the objects directly.
So, you just create Span objects and set the right properties, and add them as children to a TextBlock object.
For the XAML you posted, believe me, the XAML is much more readable and compact. For you to do this in code, you would have to instantiate the Window and the StackPanel, add the StackPanel to the Window, give the Window its title, height, and width properties, etc, etc. You're already looking at about six lines to do just that, it gets even uglier when you start instantiating the TextBlock and setting the Span.
You can absolutely use WPF without the XAML, although I'm not really sure why you would ever want to. An example of a WPF program that does just that can be found here. In fact, the reverse of your question is true. Everything you can do in XAML, you can do in C#, but not everything you can do in C#, you can do in XAML. This is because XAML maps directly do Common Runtime Language classes, properties, events, etc. but a mapping doesn't exist between every class and a piece of XAML code.
Long story short, XAML is much more maintainable and easier to edit than pure code, and requires simpler tools (an XML editor) to work with and is thus preferable to using pure code.
I am making my first WPF application, so this question may seem rather odd. I have been reading about MVVM and so far it has made sense to me. What I don't understand, though, is separating all the XAML.
What I mean is this: I assume you don't place everything in the MainWindow.xaml and just collapse controls based upon what is going to be used. I would think you would want a container that would contain xaml of other files. Is this correct?
How do you go about separating the XAML out so that it isn't just a mash of everything in one file?
How do you go about separating the XAML out so that it isn't just a mash of everything in one file?
There are many ways, including creating a seperate UserControl, CustomControl, Page or Window
For example, if you wanted to pull some XAML out of your MainWindow.xaml, you could create a UserControl (right-click project, Add, New Item..., User Control (WPF)) called MyUserControl.xaml like this:
<UserControl x:Class="WpfApplication1.MyUserControl"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Grid>
<TextBlock>This is from a different XAML file.</TextBlock>
</Grid>
</UserControl>
and then use this control in your MainWindow.xaml like this:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myControls="clr-namespace:WpfApplication1">
<Grid>
<myControls:MyUserControl/>
</Grid>
</Window>
Note that you need to add a reference to the namespace of your UserControl
xmlns:myControls="clr-namespace:WpfApplication1"
I agree with Kevin's answer about UserControl and Window, so I'll just address the follow up question:
So I should switch between various controls that are collapsed/visible in the content of my MainWindow when the user is interacting with my application?
That is a valid option. It might get messy if you are working with a large application.
The other options that I've used are
switching Views in the code behind; i.e. on the click events you can add and remove elements from the page as you would have done in WinForms. This is not pure MVVM and some people will jump down your throat, but I believe MVVM is a tool, not a religion.
provide Views as properties in your ViewModel, and bind to them from your parent View. I don't know if this is pure MVVM, it's nice when you need to dynamically create Views depending on complex conditions but it can get complicated
use DataTemplates, which are essentially rules to determine the View to use based on the type of data that is provided. So if the data is an Address (or AddressViewModel), use the AddressView. If the data is a CustomerViewModel, use the CustomerView. And so on.
DataTemplates are the preferred pattern in my opinion - clean, easy to maintain, and a nice standard. It's trivial to go to the DataTemplate to see how the binding works, whereas the other two options I've given may lead to spaghetti code in the wrong hands.
MSDN has a nice page on DataTemplates in WPF.
When using Caliburn framework you could compose your application using smaller Views and ViewModels and have a shell which binds all those smaller views together. The shell would display one or many views at the same time, depending on how you want your application to behave. The good thing about this - unlike the pattern mentioned above where you hardcode the name of the View/UserControl in other places - is that you just create a ContentControl and bind it to the correct ViewModel property and Caliburn will find the correct View for you by convention.
Let's say you have a ShellViewModel and a ShellView which is just an empty window, and another View/ViewModel where you want to display in your shell at one point. You no longer need to instantiate your views anywhere and just work your way using POCO ViewModels objects:
public class ShellViewModel : Screen
{
public ChildViewModel Child { get; set; }
public void SomeAction()
{
Child = new ChildViewModel(); //Or inject using factory, IoC, etc.
}
}
public class ShellView : Window
{
}
<Window x:Class="WpfApplication1.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://www.caliburnproject.org">
<Grid>
<ContentControl cal:View.Model="{Binding Child}" />
</Grid>
</Window>
I am trying to migrate an existing Winforms project into WPF. However: there are some user controls I need to leave as WinForm controls.
I have added a WinForms UserControl into a WPF Window. It consists of a RichTextBox and some buttons and labels. This is subclassed into various further user controls.
When I embed the UserControl into a WPF window it renders - but none of the buttons appear to do anything. When underlying processes update e.g. the RichTextBox it does not display the content. Yet when I inspect the textbox in debug I can see the content (though I have to click on 'base' to see this.)
[ One difference I have spotted - though it may not be relevant - is that when this control is on a WPF and non-working Visual Studio shows the object as 'sealed' but when in the original Winforms project when it is fully working it does not show as sealed. ]
I have added code to change the text in the labels - and they also firmly refuse to update: yet again I can see the text if I examine the label in debug mode.
This stack overflow question may address the same issue:
WindowsFormsHost Winform pdfviewer control problem
but the answer didn't make a lot of sense to me:
It mentioned replacing
new Window { Content = CreateContent(), Title = title }.Show();
But this is not a piece of code I recognise: I am using a xaml file with code behind and it's called up using
System.Windows.Application app = new System.Windows.Application();
app.Run(new FormWPFApp());
(where FormWPFApp is my name for the WPF window)
Here is the xaml header:-
<Window x:Class="ZedApp.FormWPFApp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Printers="clr-namespace:ZedApp.UserControls.Printers"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
Title="Conversion version" Height="661" Width="1559" Loaded="Window_Loaded">
Here is the xaml I use for the two UserControls (they both inherit from the same base class) :-
<WindowsFormsHost Height="430" HorizontalAlignment="Left" Margin="192,32,0,0" Name="windowsFormsHostTicketPrinter" VerticalAlignment="Top" Width="324" Grid.Row="1" Grid.Column="1">
<Printers:TicketPrinter x:Name="ticketPrinter">
</Printers:TicketPrinter>
</WindowsFormsHost>
<WindowsFormsHost Height="430" HorizontalAlignment="Left" Margin="522,32,0,0" Name="windowsFormsHostJournalPrinter" VerticalAlignment="Top" Width="324" Grid.Row="1" Grid.Column="1">
<Printers:JournalPrinter x:Name="journalPrinter">
</Printers:JournalPrinter>
</WindowsFormsHost>
[Another thing I have noticed is a method that clears the Rich Text Box on one of the windows starts kicking out errors of the following type if run under WindowsFormsHost in WPF -
"Invoke or BeginInvoke cannot be called on a control until the window handle has been created."
private void ClearRichTextBox(RichTextBox rtbToClear)
{
if (rtbToClear.IsHandleCreated)
{
if (rtbToClear.InvokeRequired)
{
this.Invoke(new Action<RichTextBox>(ClearRichTextBox), new object[] {rtbToClear});
return;
}
rtbToClear.Clear();
}
}
]
What is the likely cause of this behaviour and what do I need to do to get the elements within the User Control working?
Proper input interop with WinForms requires some cooperation between the host and the WPF input system. The topic Message Loops Between Win32 and WPF in the SDK explains this well. In your setup, the easiest way to make this happen is to use code like this:
Window w = new Window1();
System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(w);
w.Show();
ElementHost.EnableModelessKeyboardInterop() essentially registers an input hook with the WinForms Application object (which normally runs the message loop) and calls ComponentDispatcher.RaiseThreadMessage().
I'm new to WPF and the whole data binding thing. I read a couple of posts and I'm quite confused about how to bind my data to a UI element.
I saw a post doing it this way:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="myWindow">
<Grid>
<TextBox Text="{Binding Path=Speed, ElementName=myWindow}" />
</Grid>
</Window>
This assumes Speed is a property / member defined in the code-behind file. A few other people named binding using a static resource and reference this one and others named DataContext to be used for binding. Now, because I'm new to WPF's data binding, I'm quite unsure if there exists any best practice method about which data binding to use.
Basically I was wondering why there has to be a several class-property defined as kind of connector to the underlying viewmodel, I though this stuff was more "dynamically".
I'm aiming at only having the XAML file, without the need to add anything into the *.xaml.cs code behind file. For example: I have a class named MainWindowViewModel (which will represent my ViewModel) having a member of the type ObservableCollection<string> and I want to bind a ListBox (in my View) to this collection. The only way I got this working so far was using the the first case, ElementName, where I have to add a property to the view-class as a kind of connector. Just like this:
MainWindow.xaml:
<Window x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="MW" Title="MainWindow" Height="419" Width="463">
<Grid>
<ListBox ItemsSource="{Binding ElementName=MW, Path=ListerResultConnector}" />
</Grid>
</Window>
MainWindow.xaml.cs:
private ObservableCollection<string> mListerResultData = MainWindowViewModel.Instance.RetrievalStringResults;
public ObservableCollection<string> ListerResultConnector
{
get { return mListerResultData; }
}
My question is, if there exists a smarter way to bind data to my UI as using as further "connector" property in the code-behind file.
Your ViewModel should be set as the DataContext to the view. Then you don't need any "further connector" in codebehind. Binding actually refers to DataContext and if you don't set it, it remains as 'this', which corresponds to your codebehind file (which is just a partial to your view).
Also, take a look at: WPF Apps With The Model-View-ViewModel Design Pattern
You should get the WPF and it's binding basics first, but once you understand those, I suggest looking at Caliburn Micro and its convention-based bindings, event handling and other features which make your code much cleaner.
Your {Binding ElementName=MW means you are binding to the Window itself, so your DataContext is the Window, and any properties you implement need to be defined in that Window (in your code behind - your "connectors").
You need to remove the ElementName=MW bit and assign your ViewModel as the DataContext so you can bind to its properties directly. How you do this depends on whether you use "ViewModel First", or "View First"
In View first, you manually assign the DataContext to the View in code when you create the view.
In ViewModel first, you create a DataTemplate in XAML that ties your View to a particular ViewModel. I think ViewModel first is more common. The link that Darjan posted should help you understand the difference.
You should use a separate ViewModel class (WindowViewModel) which represents your data context for your Window (Window.DataContext).
I found that using the MVVM Light toolkit and following some of the videos on the site helped me fill in the gaps. Take time to learn it before getting started and it will start to sink in. IoC containers are also mixed in with MVVM + WPF for directory management & lifetime management of view models and improved design-time experience (blendability).
Toolkits aren't required and sometimes get in your way of learning the pattern. Once you understand it though, you should leverage a toolkit to speedup the development process. Here is a comparison of various MVVM toolkits.
A binding generally has two parts: a source object and a property name
When you specify ElementName in a binding, you are setting the Source object. Other ways to specify the binding's source object include the RelativeSource and Source properties. You can also leave the binding's source object undefined, in which case it will use whatever the DataContext is of the current object. The Source Object can be a UI Element found in WPF's VisualTree, or it can be a class object that is in the control's DataContext
When you specify Path, you are telling the binding what Property to use. You can also leave this property blank to bind to the current object's DataContext
The DataContext is the data object stored behind the control. This is typically a Model or a ViewModel (if using MVVM), although it can also be almost any object, such as a UI Element.
In your example
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="myWindow">
<Grid>
<TextBox Text="{Binding Path=Speed, ElementName=myWindow}" />
</Grid>
</Window>
you are telling the binding that it's Source Object is the UI Element in the Visual Tree named myWindow, and the property is called Speed. Since your object named myWindow is of type Window, this binding will only work if your Window class actually has a property called Speed.
There are a lot of answers here suggesting you switch to using the MVVM design pattern, and I agree that you should try and use MVVM if you're working with WPF. It makes coding a lot simpler since you are separating your application logic from your UI. If you're interested, I have a simple MVVM example posted on my blog which explains the basics of that design pattern.
Yeah, Binding is nothing if not confusing.
This example from msdn may be helpful. Notice how a DataContext is declared at the Window "level" - it's a complex/compound object in this case and Window sub-elements' {Binding} declarations are therefore implicitly relative to the "Parent level" DataContext.
The main goodness we get is that when the DataContext is set to a given object all the "sub element" data bindings are automagically keep in synch. We can control this synchronization at any/many levels in the UI Control structure heirarchy by using this pattern.
Collection binding under the hood
The bottom line is your collection must implement IList as a minimum. Many .NET Collection classes are "binding ready."
Here's a quote from the msnd doc on ObservableCollection:
Before implementing your own collection, consider using ObservableCollection or one of the existing collection classes, such as List, Collection, and BindingList, among many others. If you have an advanced scenario and want to implement your own collection, consider using IList, which provides a non-generic collection of objects that can be individually accessed by index. Implementing IList provides the best performance with the data binding engine.
Finally, IBinding list vs IList is needed for 2-way binding.
The simplest way to do it would be:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:WpfApplication4"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ctrl:MainWindowViewModel x:Key="mym" />
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource mym}}">
<ListBox ItemsSource="{Binding Path=MyListProp}" />
</Grid>
The example above does the following:
Creates a new object of the ViewModel as resource for you window
Assigns the view model as DataContext for the window (more precisley for the root grid)
Binds the List box to your ViewModel ObservableCollection property MyListProp.
Try to get familiar with the properties of the binding class to fully understand this example by using the msdn library.
Also WPF 4 Unleashed - Adam Nathan is a great resource for a wpf beginner. Chapter 13 - Data Binding should cover everything you might want to know about bindings.