I’m having trouble displaying lines (System.Windows.Shapes) in my view. I have a “magnifying glass” view with a hardcoded x- and y-axis in the middle, and I’m supposed to add “scale bars” to the axes (see picture below for a simplified sketch). The scale bars are dynamic, since their positions depend on the state of what is being magnified.
picture of magnifying glass with scale bars
I’m currently using a list to collect my lines. The list property itself seems to be correctly created in run time. I have managed to show lines with the same x- and y-values as in the list by hardcoding them in the view, so nothing seems to be wrong with the data itself.
Since the view model lacks a parameter less constructor, DataContext is a design instance. This has given me a lot of headache, since I haven’t been able to access the view model through code behind (DataContext is always null). I was hoping using an ItemsControl for my list of lines could still work, but so far I’ve had no luck.
Does anyone know why I’m not able to display those lines? Is there any other way of getting my data from view model to model that should work better?
A cut-down version of the code, including ItemsControl:
View:
<Window x:Class="MagnifyingGlass.MagnifyingGlassWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:MagnifyingGlassViewModel, IsDesignTimeCreatable=False}">
<Window.Resources>
<ResourceDictionary>
<DataTemplate x:Key="DataTemplate" DataType="{x:Type local:MagnifyingGlassViewModel}">
<Grid>
<ItemsControl ItemsSource="{Binding Path=ScaleBars}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Line X1="{Binding X1}" Y1="{Binding Y1}" X2="{Binding X2}" Y2="{Binding Y2}" Stroke="Black" StrokeThickness="1" Stretch="None"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Line X1="0" X2="1" Stretch="Fill" Stroke="Black" StrokeThickness="1"/> //the hardcoded y-axis
<Line Y1="0" Y2="1" Stretch="Fill" Stroke="Black" StrokeThickness="1"/> //the hardcoded x-axis
</Grid>
</DataTemplate>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ContentControl Content="{Binding}" ContentTemplate="{StaticResource DataTemplate}"/>
</Grid>
</Window>
Main view model:
namespace MagnifyingGlass
{
public class MagnifyingGlassViewModel : NotificationObject
{
public List<Line> ScaleBars => MagnifyingPlotViewModel.ScaleBars;
public MagnifyingPlotViewModel MagnifyingPlotViewModel { get; }
public MagnifyingGlassViewModel(lots of parameters here)
{
MagnifyingPlotViewModel = new MagnifyingPlotViewModel(parameters going here);
Bind(() => ScaleBars, () => MagnifyingPlotViewModel.ScaleBars);
}
}
}
View model providing the main view model with details about what is being magnified:
namespace MagnifyingGlass
{
public sealed class MagnifyingPlotViewModel : PlotViewModel
{
public List<Line> ScaleBars => GetScaleBars();
public MagnifyingPlotViewModel(parameters…)
: base(parameters…)
{
_scaleBars = new List<Line>();
// Bind adds INotifyPropertyChanged bindings so that target (first parameter) is updated/notified on dependant (source) properties (following parameters).
Bind(() => SourceToMagnify,
() => Lots, () => Of, () => Other, () => Properties);
Bind(() => ScaleBars, () => SourceToMagnify);
}
public Rect SourceToMagnify
{
get
{
return new Rect(new Point(leftOffset, 0), new Point(rightOffset, height));
}
}
private List<Line> GetScaleBars()
{
_scaleBars.Clear();
for (int i = centerX; i >= 0; i -= Delta)
{
_scaleBars.Add(new Point(i - (Delta), centerY));
}
return _scaleBars;
}
}
}
CodePudding user response:
I have managed to solve the issue myself! When debugging the application, I noticed a tab in VS I have never seen before (XAML Binding Failures). There, I could see the message:
"ItemTemplate and ItemTemplateSelector are ignored for items already of the ItemsControl's container type; Type='Line'"
So I set the stretch to none and color to black in the MagnifyingPlotViewModel when creating the lines, instead of in the xaml. Then, the first line in my list was displayed in the magnifying glass.
After reading this post, I updated my ItemsControl to the following, and now it works perfectly!
<ItemsControl ItemsSource="{Binding Path=ScaleBars}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Transparent"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>