- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我不理解 ItemTemplate 中的 DataTemplate。我有一个 ObservableCollection"StringViewModel"转录,它为 ItemsControl 提供 ItemsSource。使用 StringViewModel 填充 Transcription 集合可以正确显示这些字符串。
在显示每个字符串时,我希望 XAML 绑定(bind)调用 MyConverter,以便可以在显示的每个项目上运行附加代码。 (我不是想改变显示的内容,只是根据显示的位置执行一些操作)。
在以下代码中,MyConverter 从未被调用。
在 ItemsControl 中显示的每个项目上调用 MyConverter 的最佳方法是什么?
感谢任何帮助。
C#
public class StringViewModel : FrameworkElement {...}
private ObservableCollection<StringViewModel> transcription = new ObservableCollection<StringViewModel>();
public ObservableCollection<StringViewModel> Transcription
{
get
{
return transcription;
}
set
{
transcription = value;
}
}
XAML
<ItemsControl
ItemsSource="{Binding Transcription}"
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas
Background="Transparent"
Width="{x:Static h:Constants.widthCanvas}"
Height="{x:Static h:Constants.heightCanvas}"
/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate> <!-- THIS DOES NOT WORK -->
<ContentControl Content="{Binding Converter={StaticResource MyConverter}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
我试图将其更改为:
<ItemsControl.ItemTemplate>
<DataTemplate>
<StringViewModel ft="{Binding Path=., Converter={StaticResource MyConverter}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
结果:
ItemTemplate 和 ItemTemplateSelector 对于已经属于 ItemsControl 容器类型的项目将被忽略; Type='StringViewModel'
怎么办?
StringViewModel 定义为:
public class StringViewModel : FrameworkElement, INotifyPropertyChanged
{
public StringViewModel()
{
}
public StringViewModel(
Point topleft,
string text,
double fontsizediu,
SolidColorBrush brush,
Func<FormattedText,FormattedText> f,
double lineheight)
{
this.text = text;
this.emSize = fontsizediu;
this.color = brush;
this.topleft = topleft;
this.lineheight = lineheight;
this.f = f;
}
protected override void OnRender(DrawingContext dc)
{
ft = new FormattedText(
text,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface(new FontFamily("Segoe Script"), FontStyles.Italic, FontWeights.Normal, FontStretches.Normal),
emSize,
color);
ft.TextAlignment = TextAlignment.Left;
// apply special styles
ft = f(ft);
dc.DrawText(ft, topleft);
}
private string text;
private double emSize;
private SolidColorBrush color;
private Func<FormattedText, FormattedText> f;
public Point topleft;
private double? Lineheight;
private FormattedText _ft;
public FormattedText ft
{
get
{
return _ft;
}
set
{
if (_ft != value)
{
_ft = value;
OnPropertyChanged("ft");
}
}
}
最佳答案
更新:
我建议你不要在 ViewModel 中实现 Render,实际上你的 StringViewModel 应该是这样的 StringModel :(只是包含一些属性)
public class StringModel : INotifyPropertyChanged
{
public StringModel()
{
}
public StringModel(
Point topleft,
string text,
double fontsizediu,
SolidColorBrush brush,
double lineheight)
{
this.text = text;
this.emSize = fontsizediu;
this.color = brush;
this.topleft = topleft;
this.lineheight = lineheight;
}
public string text;
public double emSize;
public SolidColorBrush color;
public Point topleft;
public double? lineheight;
private FormattedText _ft;
public FormattedText ft
{
get
{
return _ft;
}
set
{
if (_ft != value)
{
_ft = value;
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
然后,在转换器中实现渲染:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var stringviewmodel = value as StringModel;
if (stringviewmodel != null)
{
stringviewmodel.ft = new FormattedText(
stringviewmodel.text,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface(new FontFamily("Segoe Script"), FontStyles.Italic, FontWeights.Normal, FontStretches.Normal),
stringviewmodel.emSize,
stringviewmodel.color);
stringviewmodel.ft.TextAlignment = TextAlignment.Left;
// apply special styles
Image myImage = new Image();
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext dc = drawingVisual.RenderOpen();
dc.DrawText(stringviewmodel.ft, stringviewmodel.topleft);
dc.Close();
RenderTargetBitmap bmp = new RenderTargetBitmap(180, 180, 120, 96, PixelFormats.Pbgra32);
bmp.Render(drawingVisual);
myImage.Source = bmp;
return myImage;
}
else
{
return null;
}
}
这是 itemcontrol 的代码:
<ItemsControl x:Name="ic" ItemsSource="{Binding LST}" Margin="0,0,143,185">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel
Background="Transparent"
/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding Converter={StaticResource myconverter}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
主要代码是:
public partial class MainWindow : Window
{
private List<StringModel> lst;
public List<StringModel> LST
{
get { return lst; }
set { lst = value; }
}
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
LST = new List<StringModel>();
StringModel vm = new StringModel(new Point(20, 20), "123", 14, Brushes.Red, 2);
LST.Add(vm);
vm = new StringModel(new Point(20, 20), "456", 16, Brushes.Blue, 3);
LST.Add(vm);
vm = new StringModel(new Point(20, 20), "789", 18, Brushes.Green, 4);
LST.Add(vm);
}
}
最后,它的效果:
关于c# - 如何在 ItemsControl 中绑定(bind) DataTemplate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25560594/
我正在使用 M-V-VM 并在我的 ViewModel 上有一个名为“EntitySelectedCommand”的命令。 我试图让 ItemsControl 中的所有项目来触发这个命令,但是它不起作
在我的 View 中有一个 ItemsControl,它绑定(bind)到来自 ViewModel 的 ObservableCollection。集合被填充,然后引发从 VM 到 View 的事件(想
我最近遇到了一个虚拟化问题,我将其缩小到以下代码。 虚拟化在以下代码段中不起作用的原因是因为 child 没有特定的高度。所以我的猜测是它会永远扩展并且虚拟化会中断。 给 child 一个特定的高度解
我是 WPF 的新手。我一直在尝试执行以下操作: 以下是我的数据结构: public class TokenItems {public string items {get;set;} public i
我正在尝试从 WPF MVVM 教程中扩展应用程序作为练习。对于我在这里面临的这个特定问题,我在网上没有找到解决方案。 我有一个名为“StudentsToAdd”的带有 ObservableColle
我正在使用带有 MVVM 模式的 Wpf,所以在 Xamel 中,我有一个 itemControl 持有另一个 itemcontrol,每个 itemcontrol 绑定(bind)来自不同的 Obs
标题可能听起来令人费解,但请耐心等待。 我有包含住户的房间: public class Room { public string Name { get; set; } public L
我需要能够从子 ItemsControll 数据模板内部绑定(bind)到父 ItemsControl 的属性:
这让我发疯。也许我的数据设计有误,但我正在尝试从父 ItemsControl 绑定(bind)到事件项目。 每个区域都有一种颜色,以便在屏幕上轻松识别。我没有为每个座位赋予颜色属性,而是在 Area
我的问题与此非常相似:( Binding events to buttons in an ItemsControl ) 但我没有在那里找到解决方案。我有一个 ItemsControl,在它的 Data
考虑以下 XAML
在我的主视图中,我有一个绑定(bind)到对象集合的 ItemsControl: ActivationLevelTemplate 只是另一个 View : 在这个 View 中有一
我正在使用 ItemsControl,其中 ItemsPanel 设置为 Canvas(有关更多背景信息,请参阅 this 问题)。ItemsControl 正在按我想要的方式执行,并且通过将子元素放
我有一个 ScrollViewer,里面有一个 ItemsControl。 ItemsControl 的 ItemSource 绑定(bind)到 ObservableCollection。 问题是它
我有一个带有 itemscontrol 的 WPF MVVM 应用程序。水平子项的数量受 itemscontrol 宽度的影响。只有一件事我没有解决。我试图以始终居中的方式对齐子元素。我已经用油漆制作
我有以下 XAML: 当我将数据拖到此面板上时,鼠标光标显示允许在所有子项上放置,但在任何空白区域上,光标显示禁止放置。如果我设置 AllowDro
我有一些数据要显示在 FlowDocument 中.这基本上是一个以友好方式解释数据的 View ,包括节标题、文本段落等,我将在 FlowDocumentScrollViewer 中显示这些 Vie
我有一个 ItemsControl包含我想虚拟化的数据列表,但是 VirtualizingStackPanel.IsVirtualizing="True"似乎不适用于 ItemsControl . 真
我想写一个 ItemsControl 派生的自定义控件。这部分是出于需要,部分是作为学习练习 - 请不要建议 I Style、DataTemplate、ControlTemplate 和 ListBo
我想使用ItemsControl显示重要的项目列表。 我使用ItemsControl的原因是,我正在处理的应用程序中的DataTemplate要复杂得多:提供的示例代码仅反射(reflect)了我的大
我是一名优秀的程序员,十分优秀!