英文:
How to use DataBindings in UserControls (works in page but not in uc)
问题
以下是翻译好的部分:
现在,我基本上只是复制了逻辑。我在一个名为“Components”的子文件夹中创建了一个新的UserControl:
XAML
<UserControl x:Class="WpfApp1.Components.ExampleComponent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1.Components"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ListView ItemsSource="{Binding OtherItems}" />
</Grid>
</UserControl>
C#
using System.Collections.ObjectModel;
using System.Windows.Controls;
namespace WpfApp1.Components
{
public partial class ExampleComponent : UserControl
{
private ObservableCollection<string> _otherItems;
public ObservableCollection<string> OtherItems
{
get { return _otherItems; }
set { _otherItems = value; }
}
public ExampleComponent()
{
_otherItems = new ObservableCollection<string>();
InitializeComponent();
OtherItems.Add("Other 1");
OtherItems.Add("Other 2");
}
}
}
然后,我将以下行添加到主窗口的StackPanel
中:
<Components:ExampleComponent />
以及
xmlns:Components="clr-namespace:WpfApp1.Components"
作为额外的Window
属性。
我现在得到的是第一个ListView
和第二个空的 ListView
。
我想了解为什么这不起作用,以及如何修复它。
英文:
There are several questions about this but I understand too little about the subject to understand what I am missing.
It's my first time working in WPF and I want to create several submodules (what are called UserControls I believe) to make the XAML easier to read and keep everything as its own part and potentially reusable.
I followed a YouTube video online to get the following code working:
XAML
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<ListView ItemsSource="{Binding Items}" />
</StackPanel>
</Window>
Code Behind
using System.Collections.ObjectModel;
using System.Windows;
namespace WpfApp1
{
public partial class MainWindow : Window
{
private ObservableCollection<string> _items;
public ObservableCollection<string> Items
{
get { return _items; }
set { _items = value; }
}
public MainWindow()
{
DataContext = this;
_items = new ObservableCollection<string>();
InitializeComponent();
Items.Add("Item 1");
Items.Add("Item 2");
}
}
}
Which correctly renders a ListView
with the two items.
Now I basically just copied the logic. I created a new UserControl in a subfolder "Components":
XAML
<UserControl x:Class="WpfApp1.Components.ExampleComponent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1.Components"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ListView ItemsSource="{Binding OtherItems}" />
</Grid>
</UserControl>
using System.Collections.ObjectModel;
using System.Windows.Controls;
namespace WpfApp1.Components
{
public partial class ExampleComponent : UserControl
{
private ObservableCollection<string> _otherItems;
public ObservableCollection<string> OtherItems
{
get { return _otherItems; }
set { _otherItems = value; }
}
public ExampleComponent()
{
_otherItems = new ObservableCollection<string>();
InitializeComponent();
OtherItems.Add("Other 1");
OtherItems.Add("Other 2");
}
}
}
Then I added the following line into the main window's StackPanel
:
<Components:ExampleComponent />
and
xmlns:Components="clr-namespace:WpfApp1.Components"
as an additional Window
property.
What I get now is the first ListView
and a second empty one below it.
I'd like to understand why this doesn't work, and how I can fix it.
答案1
得分: 3
你忘记设置UserControl
的DataContext
:
public ExampleComponent()
{
_otherItems = new ObservableCollection<string>();
InitializeComponent();
DataContext = this; //<--
OtherItems.Add("Other 1");
OtherItems.Add("Other 2");
}
请注意,UserControl
通常应该从其父元素继承DataContext
。
然后,您可以直接绑定到父窗口的Items
集合:
<ListView ItemsSource="{Binding Items}" />
而不是设置UserControl
的DataContext
属性并断开继承链,您可以使用RelativeSource
将绑定到UserControl
本身的特定属性:
<ListView ItemsSource="{Binding OtherItems,
RelativeSource={RelativeSource AncestorType=UserControl}}" />
英文:
You forgot to set the DataContext
of the UserControl
:
public ExampleComponent()
{
_otherItems = new ObservableCollection<string>();
InitializeComponent();
DataContext = this; //<--
OtherItems.Add("Other 1");
OtherItems.Add("Other 2");
}
Note that a UserControl
should generally speaking inherit the DataContext
from its parent element.
You can then bind directly to the Items
collection of the parent window:
<ListView ItemsSource="{Binding Items}" />
Instead of setting the DataContext
property of the UserControl
and break the inheritance chain, you could bind to a specific property of the UserControl
itself using a RelativeSource
:
<ListView ItemsSource="{Binding OtherItems,
RelativeSource={RelativeSource AncestorType=UserControl}}" />
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论