[英]Binding User control elements to Model properties
我正在尝试将UserControl
绑定到某个 model,但没有成功。
我有这个ItemsControl
:
<ItemsControl x:Name="spPatientFiles" Grid.Row="2"
ItemsSource="{Binding PatientFiles, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type uc:PatientFile}">
<uc:PatientFile/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.DataContext>
<ViewModels:MainViewModel/>
</ItemsControl.DataContext>
</ItemsControl>
它受约束
public class MainViewModel
{
public ObservableCollection<PatientFile> PatientFiles { get; set; }
public MainViewModel()
{
PatientFiles = new ObservableCollection<PatientFile>();
if (!string.IsNullOrEmpty(Models.LocalSettings.SaveFolder) &&
System.IO.Directory.Exists(Models.LocalSettings.SaveFolder))
{
var files = System.IO.Directory.GetFiles(Models.LocalSettings.SaveFolder);
foreach (var p in files)
{
var n = p.Substring(p.LastIndexOf("\\") + 1, p.LastIndexOf(".") - p.LastIndexOf("\\") - 1);
var ext = p.Substring(p.LastIndexOf(".") + 1);
PatientFiles.Add(new PatientFile()
{
FileName = n,
Path = p,
FileType = ext == "avi" ? OutputType.Video : OutputType.Image
});
}
}
}
}
主要 xaml 有视图 Model:
<Window ...
xmlns:ViewModels="clr-namespace:Octopus.Capturing.ViewModels"x:Class="Octopus.Capturing.Views.MainApp"
...>
这是我的UserControl
( uc:PatientFile
)
<UserControl ...
xmlns:Models="clr-namespace:Octopus.Capturing.Models"
x:Class="Octopus.Capturing.Views.Controls.PatientFile"
... >
<Label FontSize="10"
VerticalContentAlignment="Center" Foreground="White"
Content="{Binding FileName}"/>
但是绑定不起作用。 当我运行该应用程序时,我得到了UserControl
的结构(样式和从文件夹中读取的正确文件数),但没有绑定到文件名属性。
我在这里做错了什么?
您不应在视图 model 中拥有PatientFile
UserControl
的集合。相反,为此类用户控件 PatientFileViewModel 创建一个单独的视图PatientFileViewModel
。 实施INotifyPropertyChanged
以启用通知控件更新已更改的属性。
public class PatientFileViewModel : INotifyPropertyChanged
{
private string _fileName;
public string FileName
{
get => _fileName;
set
{
if (_fileName == value)
return;
_fileName = value;
OnPropertyChanged();
}
}
// ...implement the other properties like this, too.
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
调整您的ItemTemplate
以显示PatientFileViewModel
的PatientFile
用户控件。
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type uc:PatientFileViewModel}">
<uc:PatientFile/>
</DataTemplate>
</ItemsControl.ItemTemplate>
接下来,从您的PatientFile
用户控件中删除现在位于视图 model 中的属性和代码。 您可以保留其 XAML 代码。 Label
的内容现在将绑定到数据上下文,即在应用DataTemplate
时由ItemsControl
自动设置的PatientFileViewModel
。
最后调整您的MainViewModel
以创建和使用PatientFileViewModel
而不是PatientFile
。
public class MainViewModel
{
public ObservableCollection<PatientFileViewModel> PatientFiles { get; set; }
public MainViewModel()
{
PatientFiles = new ObservableCollection<PatientFileViewModel>();
if (!string.IsNullOrEmpty(Models.LocalSettings.SaveFolder) &&
System.IO.Directory.Exists(Models.LocalSettings.SaveFolder))
{
var files = System.IO.Directory.GetFiles(Models.LocalSettings.SaveFolder);
foreach (var p in files)
{
var n = p.Substring(p.LastIndexOf("\\") + 1, p.LastIndexOf(".") - p.LastIndexOf("\\") - 1);
var ext = p.Substring(p.LastIndexOf(".") + 1);
PatientFiles.Add(new PatientFileViewModel()
{
FileName = n,
Path = p,
FileType = ext == "avi" ? OutputType.Video : OutputType.Image
});
}
}
}
}
确保将主视图的DataContext
设置为MainViewModel
,例如:
<Window xmlns:ViewModels="clr-namespace:Octopus.Capturing.ViewModels"x:Class="Octopus.Capturing.Views.MainApp"
...>
<Window.DataContext>
<ViewModels:MainViewModel/>
</Window.DataContext>
<!-- ...other code. -->
</Window>
此外,您应该删除ItemsSource
绑定上的Mode=TwoWay
和UpdateSourceTrigger=PropertyChanged
,这不是必需的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.