[英]WPF Binding with DataContext on Custom Content Control
我有一個自UserControl
派生的自定義向導控件WizardControl
,該UserControl
具有一個名為Pages
的依賴項屬性,其自定義類集合的數據類型為WizardPageCollection
。
WizardControl
托管在一個帶有稱為MainViewModel
的視圖模型的Window
,該向導的頁面使用XAML實例化。
我試圖將頁面綁定到聲明為MainViewModel
屬性的子視圖模型Page1VM
和Page2VM
。
DataContext
與Page1VM
的第一頁綁定工作正常,但是第二頁的綁定失敗,並顯示以下錯誤消息:
System.Windows.Data Error: 3 : Cannot find element that provides DataContext. BindingExpression:Path=Page2VM; DataItem=null; target element is 'MyPage' (Name=''); target property is 'DataContext' (type 'Object')
問:為什么綁定在第一頁上起作用,但是在第二頁上失敗,有什么辦法可以MainViewModel
起作用,同時仍將MainViewModel
聲明在MainWindow
的DataContext
XAML標記內? 我不想將ViewModel用作字典資源,因為這會對我們產生一些影響,我將不做詳細介紹。
如評論員所建議,如果我按如下所示更改綁定以使用RelativeSource:
<common:MyPage DataContext="{Binding DataContext.Page1VM, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
<common:MyPage DataContext="{Binding DataContext.Page2VM, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
第一個綁定可以正常運行,但是第二個綁定仍然失敗,但是帶有不同的錯誤消息(如預期的那樣):
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=DataContext.Page2VM; DataItem=null; target element is 'MyPage' (Name=''); target property is 'DataContext' (type 'Object')
謝謝你的時間!
我的代碼清單如下所示:
MainWindow XAML:
<Window.DataContext>
<common:MainViewModel />
</Window.DataContext>
<Grid>
<common:WizardControl>
<common:WizardControl.Pages>
<common:WizardPageCollection>
<common:MyPage DataContext="{Binding Page1VM}" />
<common:MyPage DataContext="{Binding Page2VM}" />
</common:WizardPageCollection>
</common:WizardControl.Pages>
</common:WizardControl>
</Grid>
MainViewModel和PageViewModel:
public class MainViewModel
{
public PageViewModel Page1VM
{
get;
set;
}
public PageViewModel Page2VM
{
get;
set;
}
public MainViewModel()
{
this.Page1VM = new PageViewModel("Page 1");
this.Page2VM = new PageViewModel("Page 2");
}
}
public class PageViewModel
{
public string Title { get; set; }
public PageViewModel(string title) { this.Title = title; }
}
WizardControl XAML:
<Grid>
<ContentPresenter Grid.Row="0" x:Name="contentPage"/>
</Grid>
WizardControl的代碼背后:
public partial class WizardControl : UserControl
{
public WizardControl()
{
InitializeComponent();
}
public WizardPageCollection Pages
{
get { return (WizardPageCollection)GetValue(PagesProperty); }
set { SetValue(PagesProperty, value); }
}
public static readonly DependencyProperty PagesProperty =
DependencyProperty.Register("Pages", typeof(WizardPageCollection), typeof(WizardControl), new PropertyMetadata(new WizardPageCollection(), new PropertyChangedCallback(Pages_Changed)));
static void Pages_Changed(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
WizardPageCollection col = e.NewValue as WizardPageCollection;
WizardControl ctrl = obj as WizardControl;
ctrl.contentPage.Content = col.First();
}
}
public class WizardPageCollection : ObservableCollection<WizardPageBase> { }
public class WizardPageBase : ContentControl { }
MyPage XAML:
<Grid>
<Label Content="{Binding Title}" />
</Grid>
您的方法取決於Window的DataContext
屬性的值繼承 ,該屬性對您的WizardPageCollection不起作用,因為它不會形成WPF元素樹。
您應該改為將MainViewModel創建為資源,然后通過StaticResource
進行引用:
<Window ...>
<Window.Resources>
<common:MainViewModel x:Key="MainViewModel"/>
</Window.Resources>
<Window.DataContext>
<Binding Source="{StaticResource MainViewModel}"/>
</Window.DataContext>
<Grid>
<common:WizardControl>
<common:WizardControl.Pages>
<common:WizardPageCollection>
<common:MyPage DataContext="{Binding Page1VM,
Source={StaticResource MainViewModel}}"/>
<common:MyPage DataContext="{Binding Page2VM,
Source={StaticResource MainViewModel}}"/>
</common:WizardPageCollection>
</common:WizardControl.Pages>
</common:WizardControl>
</Grid>
</Window>
@Clemens回答解決問題的方法,但問題是其他的,恕我直言。
將項目添加到WizardPageCollection時,也應將其添加到LogicalTree。 查看ItemsControl的來源以獲取靈感。 絕對有可能使綁定工作保持原樣。
我將在這里使用viewmodel first方法。 將頁面定義為頁面視圖模型的集合並生成視圖。 最后,xaml如下所示:
<common:WizardControl PagesSource="{Binding Pages}"> <common:WizardControl.PageTemplate> <DataTemplate> <common:MyPage DataContext="{Binding }" /> </DataTemplate> </common:WizardControl.PageTemplate> </common:WizardControl>
或者,考慮您的WizardControl
是從Selector
類而不是usercontrol派生的。 (選擇器是列表框中的基類。它具有itemssource和選定的項目)。
<common:WizardControl ItemsSource="{Binding Pages}"
SelectedItem="{Binding SelectedPage}">
<common:WizardControl.ItemTemplate>
<DataTemplate>
<common:MyPage DataContext="{Binding }" />
</DataTemplate>
</common:WizardControl.ItemTemplate>
</common:WizardControl>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.