如何在绑定时获取类型的属性

时间:2014-12-04 11:46:16

标签: c# xaml mvvm binding parent

我有一个名为“MyType”的类型,我的Pivot的ItemsSource绑定到“myFirstVM”ViewModel中名为“DataSource”的ObservableCollection属性。在“MyType”里面我有属性Title。正如您从我的XAML中看到的,TextBlock绑定到MyProperty。如何让它返回当前项目标题?

所以例如,如果我在第二个PivotItem上,我需要DataSource集合中第二个项目的标题

XAML:

<Grid x:Name="LayoutRoot">
    <Pivot Name="myPivot"
           SelectedItem="{Binding myFirstVM.SelItem, Mode=TwoWay}"
           ItemsSource="{Binding myFirstVM.DataSource}"
           ItemTemplate="{Binding myFirstVM.OtherTemplate}">
        <Pivot.HeaderTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding DataContext.myFirstVM.MyProperty, ElementName=myPivot}"/>
            </DataTemplate>
        </Pivot.HeaderTemplate>
    </Pivot>
</Grid>

myFirstVM代码:

private ObservableCollection<MyType> _dataSource;
public ObservableCollection<MyType> DataSource
{
    get
    {
        if (this._dataSource == null)
        {
            this._dataSource = new ObservableCollection<MyType>();
        }
        return this._dataSource;
    }
    set { }
}

public string MyProperty 
{ 
    get
    {
        if (null != this.SelItem)
        {
            return this.SelItem.Title;
        }

        return "no title";
    } 
    set { }
}

private MyType _selItem;
public MyType SelItem
{
    get
    {
        return _selItem;
    }
    set
    {
        _selItem = value;

        RaisePropertyChanged("SelItem");
        RaisePropertyChanged("MyProperty");
    }
}

public ObservableCollection<MyOtherType> OtherDataSource
{
    get
    {
        if (null != this.SelItem)
        {
            return this.SelItem.OtherCollection;
        }
        else
        {
            return new ObservableCollection<MyOtherType>();
        }
    }
    set { }
}

private MyOtherType _selOtherItem;
public MyOtherType SelOtherItem
{
    get
    {
        return _selSegment;
    }
    set
    {
        _selSegment = value;

        RaisePropertyChanged("SelOtherItem");
        RaisePropertyChanged("PartsDataSource");
    }
}

public ObservableCollection<MyThirdType> ThirdDataSource
{
    get
    {
        if (null != this.SelOtherItem)
        {
            return this.SelOtherItem.ThirdCollection;
        }
        else
        {
            return new ObservableCollection<MyThirdType>();
        }
    }
    set { }
}

这些是我的DataTemplates,用于内部集合“OtherDataSource”和“ThirdDataSource”,即ListBoxes:

<DataTemplate x:Key="OtherTemplate">
    <ListBox DataContext="{Binding Source={StaticResource Locator}}"
             ItemsSource="{Binding myFirstVM.OtherDataSource}"
             ItemTemplate="{StaticResource ThirdTemplate}"
             SelectedItem="{Binding myFirstVM.SelOtherItem, Mode=TwoWay}">
    </ListBox>
</DataTemplate>

<DataTemplate x:Key="ThirdTemplate">
    <ListBox DataContext="{Binding Source={StaticResource Locator}}"
             ItemsSource="{Binding myFirstVM.ThirdDataSource}"
             ItemTemplate="{StaticResource FourthTemplate}">
    </ListBox>
</DataTemplate>

编辑:我用完整的ViewModel和DataTemplates更新了问题,就像@olite一样。你可以看到这种方法的问题是在第二个和第三个dataTemplate中我有ListBoxes。我正在使用一个ViewModel来处理所有事情。有什么想法吗?

3 个答案:

答案 0 :(得分:1)

你需要做一些额外的工作。您的ViewModel当前不知道选择了哪个项目。您可以创建一个名为'SelectedItem'的新属性,并绑定Pivots的SelectedItem值。

然后您可以在代码中访问所选项目。

<Grid x:Name="LayoutRoot">
   <Pivot Name="myPivot"
       Tag="{Binding}"
       SelectedItem="{Binding myFirstVM.SelectedItem}"
       ItemsSource="{Binding myFirstVM.DataSource}"
       ItemTemplate="{Binding myFirstVM.ViewDataTemplate}">
   <Pivot.HeaderTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding DataContext.myFirstVM.MyProperty, ElementName=myPivot}"/>
        </DataTemplate>
   </Pivot.HeaderTemplate>
</Pivot>
</Grid>

然后你的VM看起来像:

private ObservableCollection<MyType> _dataSource;
public ObservableCollection<MyType> DataSource
{
    get
    {
        if (this._dataSource == null)
        {
            this._dataSource = new ObservableCollection<MyType>();
        }
        return this._dataSource;
    }
    set { }
}

public string MyProperty 
{ 
    get
    {
        if (this.SelectedItem != null)
        {
            return this.SelectedItem.Title;
        }
        else
        {
            return null;
        }
    } 
}

private MyType _selectedItem;

public MyType SelectedItem
{ 
    get
    {
        return _selectedItem;
    } 
    set
    {
        _selectedItem = value;
        OnNotifyPropertyChanged("SelectedItem");
        OnNotifyPropertyChanged("MyProperty");
    }
}

或者,如果您只是想要修改文本以进行演示,并且实际上并不需要VM中的SelectedItem,那么您可以使用@ Jehof的方法 - 但实现执行修复的IValueConvertor。

答案 1 :(得分:0)

这应该可以解决问题

<TextBlock Text="{Binding SelectedItem.Title, ElementName=myPivot}"/>

将Text-Property绑定到Pivot元素的SelectedItem属性。当所选的Pivot项目发生更改时,TextBlock应显示项目的标题。

答案 2 :(得分:0)

这是正确的XAML实现:

SelectedItem="{Binding myFirstVM.SelectedItem, Mode=TwoWay}"

并且在代码后面而不是OnNotifyPropertyChanged中,ViewModel需要继承ViewModelBase,MVVM Light的一部分然后在SelectedItem属性的setter中:

RaisePropertyChanged("SelectedItem");