I'm just learning WPF and I could use some help. I have an application which use TabControl and dynamically generates new tabs,on each Tab I have one TextBox and now I'd like to add an undo button to the tool bar which is not the part of the tab (VisualStudio like). The undo button has to work only on the TextBox wich is on the active tab and if there is no tab or the undo can't be executed it will be disabled. And I have no idea how to 开发者_StackOverflow中文版bind these two items (The tab content has it own xaml file).
Only thing I succeed is adding an click eventHandler to the MenuItem and then finding the text box on the active tab by name, but now I can't enable/disable like I'd wish.
I hope it is understandable. Thanks for any help
I've made an example to illustrate the "right WPF way" to go about this scenario. Again, it might not match the code you already have, but it should give you some ideas on how to adapt your code. First, the code-behind:
public partial class TabItemBinding : Window
{
public ObservableCollection<TextItem> Items { get; set; }
public TabItemBinding()
{
Items = new ObservableCollection<TextItem>();
Items.Add(new TextItem() { Header = "1", Content = new TextBox() { Text = "First item" } });
Items.Add(new TextItem() { Header = "2", Content = new TextBox() { Text = "Second item" } });
Items.Add(new TextItem() { Header = "3", Content = new TextBox() { Text = "Third item" } });
InitializeComponent();
}
}
public class TextItem
{
public string Header { get; set; }
public FrameworkElement Content { get; set; }
}
Nothing crazy here, I'm just creating a model class and setting up a collection of that class. The real goodness happens in the XAML:
<Window x:Class="TestWpfApplication.TabItemBinding"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TabItemBinding" Height="300" Width="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ToolBar Grid.Row="0">
<Button Command="Undo">Undo</Button>
</ToolBar>
<TabControl Grid.Row="1" ItemsSource="{Binding Items}">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding Header}"/>
<Setter Property="Content" Value="{Binding Content}"/>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
</Grid>
I hook up the Button
to ApplicationCommands.Undo
, which will automatically take care of the undo for us as long as we have an active editing TextBox
. The TabControl
itself is bound to the collection we made in the code-behind, which will provide a header and some text to edit. And any edits we make will be undo-able. The result:
Screenshot http://img706.imageshack.us/img706/2866/tabitembinding.png
By the way, it's important to note that the undo command will automatically disable itself if there is not an active editing context. So if there are no tab pages, it will be disabled without any extra code on our part.
What you want would be done much easier with WPF's built-in Command system. Basically, it has a built-in "CanExecute" event, in which you could check the TabControl's selected page and so on. It's hard to give a concrete example without any example code to work with, but hopefully this will set you on the right path.
You might be interested in the Writer sample application of the WPF Application Framework (WAF) project. It shows a simple editor with a Tabbed MDI (similar to Visual Studio) and it implements the Undo/Redo function. This might be exactly what you are looking for.
精彩评论