How do you set a non-dependancy property from the viewmodel for a dynamic control
I know my subject line is a bit confusing, and that is either because I have confused myself so totally that I am missing a simple solution or that this really is one of those tough nuts.
My view has a portion that is a set of tabs that are created based on an observable list in the viewmodel. Each tab has a couple of embedded controls, one of which is a RichTextBox. One of the big limitations of a RichTextBox is that the Document is not a dependency property, and I know one solution would be to sub-class the control and just add a dependency property.
I have approached this problem from a couple of directions, and I am just not making headway must likely due to my still growing knowledge of .net. I believe my biggest problem is the separation of the view and VM. My view has the VM as a data source, and my original group of 8 items is correctly generated. However, even though the class used in the observable list has a flowdocument as one of its items there is no XAML way to bind that flowdocument to the RichTextBox. There does not seem to be a newTabAdded type event for TabControl and the Initialized event for the RichTextBox does not seem to even make it to the code behind in the View. Even if I could capture a useful event in the code behind I can not seem to understand how the Relay command works on a control that does not implement the ICommand source to pass the event to my VM.
So my question is, what pattern or class is used that will allow access in the VM to a specific control in the view that is created dynamically based on an observable list and can change dynamically during runtime? I am doing this under VS2010 Professional for .net4.0 and have access to blend as well. My current requirement is to set the document only once, but in a perfect world I would prefer to be able to change the document.
Here is the current XAML
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Luna"
xmlns:CustomControlLibrary="clr-namespace:CustomControlLibrary;assembly=CustomControlLibrary"
x:Class="ClientUI.View"
Title="ViewWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="BSwitchTemplate">
<StackPanel x:Name="Switch_Listing">
<Button Content="{Binding SwitchInstance.boxName, Mode=OneWay}" Width="75" Style="{DynamicResource swmainbuttonTemplate}">
<Button.Resources>
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="3" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<LinearGradientBrush x:Key="ButtonNormalBackgroundFill" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#FFF0F0EA" Offset="0.9"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="ButtonBorder" Color="#FF003C74"/>
<Style x:Key="swmainbuttonTemplate" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
<Setter Property="Background" Value="{StaticResource ButtonNormalBackgroundFill}"/>
<Setter Property="BorderBrush" Value="{StaticResource ButtonBorder}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RenderDefaulted="{TemplateBinding IsDefaulted}" SnapsToDevicePixels="true" ThemeColor="NormalColor">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Microsoft_Windows_Themes:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="true">
<Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Resources>
</Button>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="Template_swTabHeader">
<Grid Height="Auto" Width="Auto">
<TextBlock TextWrapping="Wrap" Text="{Binding SwitchInstance.boxName, Mode=OneWay}" FontFamily="Times New Roman" FontSize="13.333" HorizontalAlignment="Center" Width="Auto" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="Template_swTabContent">
<Grid>
<RichTextBox x:Name="richTextBox" Margin="0,0,8,23.84" FontFamily="Lucida Console" Initialized="AssignDocument">
</RichTextBox>
<CustomControlLibrary:CLI_EntryBox HorizontalAlignment="Stretch" Height="20.5" Margin="2,0,8,0" TextWrapping="Wrap" Text="CLI_EntryBox" VerticalAlignment="Bottom"/>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource VMDataSource}}">
<Grid.Row开发者_StackOverflow中文版Definitions>
<RowDefinition Height="0.552*"/>
<RowDefinition Height="0.448*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.454*"/>
<ColumnDefinition Width="0.546*"/>
</Grid.ColumnDefinitions>
<ListBox x:Name="mainswitchlist" HorizontalAlignment="Left" Margin="8,8,0,34.5" Width="105" SelectionMode="Multiple" ItemTemplate="{DynamicResource BSwitchTemplate}" ItemsSource="{Binding fabric_switches}" FontFamily="Times New Roman" Grid.RowSpan="2" />
<TabControl x:Name="swTabs" Margin="117,8,51,34.5" Grid.ColumnSpan="2" ItemsSource="{Binding fabric_switches}" ItemTemplate="{DynamicResource Template_swTabHeader}" ContentTemplate="{DynamicResource Template_swTabContent}" Grid.RowSpan="2" DataContext="{StaticResource VMDataSource}" SelectionChanged="swTabs_SelectionChanged" />
<Button Content="Button" Grid.Column="1" Height="26" HorizontalAlignment="Left" Margin="242,18,0,0" Name="button1" VerticalAlignment="Top" Width="27" />
</Grid>
Couple of options:
- An attached behavior
- Use an
EventSetter
in theItemContainerStyle
for theTabControl
to perform some logic when eachTabItem
loads.
精彩评论