none
如何获取绑定真实的根级绑定源?MVVM RRS feed

  • 问题

  • 在View里

            [Import]
            MaterialCategorysViewModel ViewModel
            {
                set 
                {
                    this.DataContext = value;
                }
            }
    

    在view里我有一个Tab控件:

     <TabControl Grid.Row="1"  Name="tabControl1" SelectedIndex="{Binding SelectedTabIndex}">
                    <TabItem Header="概览" >
                        <!--local:MaterialCategoryListView DataContext="{Binding}"/-->
                        <TreeView Name="CategoryTreeView" ItemsSource="{Binding Path=Model}"  
                         ItemTemplate ="{StaticResource NavigationTemplate }" >
                            <TreeView.ItemContainerStyle>
                                <!-- This Style binds a TreeViewItem to a PersonViewModel.  -->
                                <Style TargetType="{x:Type TreeViewItem}">
                                    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
                                    <Setter Property="FontWeight" Value="Normal" />
                                    <Style.Triggers>
                                        <Trigger Property="IsSelected" Value="True">
                                            <Setter Property="FontWeight" Value="Bold" />
                                        </Trigger>
                                    </Style.Triggers>
                                </Style>
                            </TreeView.ItemContainerStyle>
                    
                        </TreeView>
                    </TabItem>
                    <TabItem Header="基本" Name="tabItem1" DataContext="{Binding ElementName=CategoryTreeView, Path=SelectedItem}">
                         <Grid >
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="45*" />
                                <RowDefinition Height="387*" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="52" />
                                <ColumnDefinition Width="265" />
                                <ColumnDefinition Width="117" />
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="51" />
                                <ColumnDefinition Width="115*" />
                            </Grid.ColumnDefinitions>
                            <Label Content="名称:" Height="28" HorizontalAlignment="Left" Margin="12,6,0,0" Name="label1" VerticalAlignment="Top" />
                            <Label Content="描述:" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,5,0,0" Name="label2" VerticalAlignment="Top" />
                            <TextBox Grid.Column="1" 
                     Name="textBoxName"
                     Height="23" 
                     HorizontalAlignment="Left"
                     Margin="9,8,0,0"
                     VerticalAlignment="Top" Width="250" 
                     Text="{jas:FocusBinding Path=Name, ValidatesOnDataErrors=True}"
                     >
                                <i:Interaction.Behaviors>
                                    <behaviors:FocusBehavior></behaviors:FocusBehavior>
                                </i:Interaction.Behaviors>
                            </TextBox>
    
    
                            <TextBox Grid.Column="1" 
                     Grid.Row="1" 
                     Height="23" 
                     HorizontalAlignment="Left" 
                     Margin="9,7,0,0" 
                     Name="textBox2" 
                     VerticalAlignment="Top" 
                     Width="365" Grid.ColumnSpan="2" 
                     Text="{Binding Path=Description}"/>
                            <csla:PropertyStatus Grid.Column="2" Margin="11,11,86,3" Name="propertyStatus1" Width="20" Height="20" Property="{Binding Path=Name }" />
                            <csla:PropertyStatus Grid.Column="4" Grid.Row="1" Margin="12,7,19,7" Name="propertyStatus2" Width="20" Height="20" Property="{Binding Path=Description}" />
    
                        </Grid>
                    </TabItem>
                </TabControl>
    


    如何从 text控件 textBoxName可以获取绑定的 this.DataContext = value;既ViewModel?



    2011年9月6日 5:40

答案

  • Ok, 看来你使用了MEF,而且你里面还有一个 custom markup extension {jas:FocusBinding }. 当然对于这个markup extension 我肯定不是很了解,如果你觉得这个问题和这个相关的话,最好是提供下这些的具体信息。

    不过你的问题是如何 当前 View 的 DataContext. 如果与MEF和上述markup extension无关的话,简单的做法就是:假如说你的View是一个 UserControl 类型的,你就可以用RelativeSource去找到这个View实例,然后设置这个TextBox的DataContext.

        <TextBox Grid.Column="1" 
                 Name="textBoxName"
                 Height="23" 
                 HorizontalAlignment="Left"
                 Margin="9,8,0,0"
                 VerticalAlignment="Top" Width="250" 
                 Text="{jas:FocusBinding Path=Name, ValidatesOnDataErrors=True}"
                 DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserCotnrol}}, Path=DataContext}">
          <i:Interaction.Behaviors>
            <behaviors:FocusBehavior></behaviors:FocusBehavior>
          </i:Interaction.Behaviors>
        </TextBox>
    

    Sincerely,


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 Cuiqs 2011年9月8日 15:43
    2011年9月7日 5:56
    版主
  • DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserCotnrol}}, Path=DataContext}"

    这个可以了,不过必须加上:,AncestorLevel=2。 因为我是UserControl里含有UserControl.

    • 已标记为答案 Cuiqs 2011年9月8日 15:43
    2011年9月8日 15:43

全部回复

  • 是俺的问题描述不够清楚吗?

     

    2011年9月7日 0:31
  • 别急,论坛上是不是实时都能回复的。我们需要点时间来看下,不过今天肯定我会给你一个回复的。
    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年9月7日 2:42
    版主
  • Ok, 看来你使用了MEF,而且你里面还有一个 custom markup extension {jas:FocusBinding }. 当然对于这个markup extension 我肯定不是很了解,如果你觉得这个问题和这个相关的话,最好是提供下这些的具体信息。

    不过你的问题是如何 当前 View 的 DataContext. 如果与MEF和上述markup extension无关的话,简单的做法就是:假如说你的View是一个 UserControl 类型的,你就可以用RelativeSource去找到这个View实例,然后设置这个TextBox的DataContext.

        <TextBox Grid.Column="1" 
                 Name="textBoxName"
                 Height="23" 
                 HorizontalAlignment="Left"
                 Margin="9,8,0,0"
                 VerticalAlignment="Top" Width="250" 
                 Text="{jas:FocusBinding Path=Name, ValidatesOnDataErrors=True}"
                 DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserCotnrol}}, Path=DataContext}">
          <i:Interaction.Behaviors>
            <behaviors:FocusBehavior></behaviors:FocusBehavior>
          </i:Interaction.Behaviors>
        </TextBox>
    

    Sincerely,


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 Cuiqs 2011年9月8日 15:43
    2011年9月7日 5:56
    版主
  • 谢谢,Bobo

    {jas:FocusBinding } 在这里是个关键。 我需要在ViewModel控制View里的控件的Focus. Jas:FocusBinding可以参考http://joshsmithonwpf.wordpress.com/2010/03/16/control-input-focus-from-viewmodel-objects/

    现在的问题是这样的。我在ViewModel里继承了这个扩展的IFocusMover接口:

     public class MaterialCategorysViewModel:ViewModel<MaterialCategorys>,IFocusMover

    在View里,我用TreeView来绑定MaterialCategorys. 然后用下面的表达式来绑定Treeview里的选定的行"{Binding ElementName=CategoryTreeView, Path=SelectedItem}">

    然后再绑定到这个行里的列,如Text="{jas:FocusBinding Path=Name, ValidatesOnDataErrors=True}".

    Focusbinding这个扩展:

     

    public class FocusBinding : BindingDecoratorBase
        {
            public override object ProvideValue(IServiceProvider provider)
            {
                DependencyObject elem;
                DependencyProperty prop;
                if (base.TryGetTargetItems(provider, out elem, out prop))
                {
                    FocusController.SetFocusableProperty(elem, prop);
                }
    
                return base.ProvideValue(provider);
            }
        }
    


    这个扩展会获取textName以及我绑定的属性Text。 在这个扩展里,他通过:element.GetValue(FrameworkElement.DataContextProperty)获取这个控件的DataContextProperty. 如果对于这个控件是直接绑定到Usercontrol的Datacontext

    的,就相当于直接绑定到了ViewModel。但是对于我的情况不一样,我的TextBox是绑定到TreeView的SelectedItem。 TreeView是绑定到Model。 Model是属于ViewModel

    里的一个属性: public static readonly DependencyProperty ModelProperty;

    儿现在用到这个:element.GetValue(FrameworkElement.DataContextProperty)。获取的只是一个Collection。而不是ViewModel. 所以我的问题是如何才能获取真实的绑定源头啊?

    MaterialCategorysViewModel=>Model=>SelectedItem=>Name。 就是从Name怎么能够获取MaterialCategorysViewModel(ViewModel)这个绑定?

     

    static void CreateHandler(DependencyObject elemnt, DependencyProperty property)
            {
                var focusMover = element.GetValue(FrameworkElement.DataContextProperty) as IFocusMover;
                if (focusMover == null)
                {
                    var handler = element.GetValue(MoveFocusSinkProperty) as MoveFocusSink;
                    if (handler != null)
                    {
                        handler.ReleaseReferences();
                        element.ClearValue(MoveFocusSinkProperty);
                    }
                }
                else
                {
                    var handler = new MoveFocusSink(element as UIElement, property);
                    focusMover.MoveFocus += handler.HandleMoveFocus;
                    element.SetValue(MoveFocusSinkProperty, handler);
                }
            }
    


     

    2011年9月8日 1:28
  • 额,看了你的描述,我觉得我的那个代码是可以解决你的问题的,通过RelativeSource把跟元素的DataContext引导到当前TextBox里来。你试一下。


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年9月8日 3:44
    版主
  • 我没有用到Datacontext.

     [Import]
            MaterialCategorysViewModel ViewModel
            {
                set
                {
                    var src = (System.Windows.Data.CollectionViewSource)(this.FindResource("MaterialCategorysViewModelSource"));
                    src.Source = new List<object> { value };
                    
                }
            }
    


    在父窗体用到的是:

      <ad:DockableContent.Resources >
            <CollectionViewSource x:Key="MaterialCategorysViewModelSource"/>
    
        </ad:DockableContent.Resources>
    

    我如何访问这个CollectionViewSource ?

    2011年9月8日 8:23
  • 那你就可以用 StaticResoruce 来设置 TextBox的DataContext了:

        <TextBox DataContext="{Binding Source={StaticResource MaterialCategorysViewModelSource}}" .../>
    


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年9月8日 9:45
    版主
  • DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserCotnrol}}, Path=DataContext}"

    这个可以了,不过必须加上:,AncestorLevel=2。 因为我是UserControl里含有UserControl.

    • 已标记为答案 Cuiqs 2011年9月8日 15:43
    2011年9月8日 15:43