I have a problem displaying an image in WPF. The problem is that I add the image into the Grid and I can not actually see the image. I can see the place where the image is, but not the image itself (check the image below):
Here is my code:
View:
<DataGridTemplateColumn Header="Image" Width="SizeToCells" IsReadOnly="True" Visibility="Visible">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Height="25" Width="50" Source="{Binding Path=ImageArticle}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Here I take the path and add it:
ContinueArticle ca = new ContinueArticle();
string ImagePath = Environment.CurrentDirectory + #"C:\iClipIT\Thumbs\" + ClipID;
ca.ImageArticle = ImagePath;
atlist.Add(ca);
And here I create the object and the getters and setters:
public static readonly DependencyProperty ArticleImageProperty
= DependencyProperty.Register("ArticleImage", typeof(string), typeof(ContinueArticle));
public string ImageArticle
{
get
{
return (string)GetValue(ArticleImageProperty);
}
set
{
SetValue(ArticleImageProperty, value);
}
}
Any clue what I'm doing wrong? I read a lot about this and I can't find the problem.
Related
Faced the need to select a fragment of text in TextBlock, namely certain keywords on which the ListBox was filtered, this text block itself and containing
XAML variant, title property is not bound
<ListBox Name="ProcedureList" ItemsSource="{Binding Path=ProceduresView.View}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Name="ProcedurePanel" PreviewMouseDown="ProcedurePanel_OnPreviewMouseDown">
<DockPanel Width="{c:Binding ElementName=MainPanel, Path=Width-40}">
<!--<TextBlock Name="MainText" TextWrapping="Wrap" FontSize="16" Text="{Binding Path=title}" HorizontalAlignment="Left" />-->
<htb:HighlightTextBlock Name="MainText" TextWrapping="Wrap" FontSize="16" Text="{Binding Path=title}" HorizontalAlignment="Left">
<htb:HighlightTextBlock.HighlightRules>
<htb:HighlightRule
IgnoreCase="{Binding IgnoreCase, Source={StaticResource SourceVm}}"
HightlightedText="{Binding Path=title, Converter={StaticResource getFilter}}">
<htb:HighlightRule.Highlights>
<htb:HighlightBackgroung Brush="Yellow"/>
</htb:HighlightRule.Highlights>
</htb:HighlightRule>
</htb:HighlightTextBlock.HighlightRules>
</htb:HighlightTextBlock>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
A component written by our compatriot with open source is used
Component
Description of component
The commented code is an old TexBlock with no selection
The new HighlightTextBlock component perfectly selects the text if you use a static resource, as in the example, but when I try to bind it to the current text it can not find this field :(, I'm new in WPF help figure it out
HightlightedText="{Binding Path=title, Converter={StaticResource getFilter}}"
How correctly to anchor this property to title?
DataContext structure
public ObservableCollection<Procedure> Procedures { set; get; }
public CollectionViewSource ProceduresView { set; get; } = new CollectionViewSource();
....
Procedures = new ObservableCollection<Procedure>();
ProceduresView.Filter += Procedures_Filter;
ProceduresView.Source = Procedures;
....
public class Procedure : ObservableObject
{
....
public String title { get; set; }
....
}
....
// Simple filtering
void Procedures_Filter(object sender, FilterEventArgs e)
{
Procedure procedure = (Procedure) e.Item;
Boolean flag = false;
if (!string.IsNullOrEmpty(filter))
{
Setting.Filter sfilter = new Setting.Filter();
sfilter.type = "искать везде";
sfilter.text = filter;
ObservableCollection<Setting.Filter> arr = new ObservableCollection<Setting.Filter>();
arr.Add(sfilter);
if (Utils.AssignedProcedureFromFilter(procedure, arr)) flag = true;
}
else flag = true;
e.Accepted = flag;
}
Video with problem description
Simplified project emitting my functional
On the Russian-speaking forum they explained to me that:
Your case, in fact, is more serious. DataContext you, apparently, the
right one. But your Binding expression is inside the HighlightRules
property setter, which is not part of the visual tree (because it is
not available as a Child element of your control). And elements that
are not inside the visual tree, participate in bindings are only
limited: they do not inherit DataContext, nor access by name through
ElementName. As a solution, bind to an element via x: Reference. In my
(heavily cut) test case, HightlightedText = "{Binding Path =
DataContext.title, Source = {x: Reference MainText}} is triggered."
But, if directly replaced by this, a strange error works: 'Can not
call MarkupExtension. ProvideValue because of a cyclic dependency. The
properties inside the MarkupExtension can not reference objects that
reference the MarkupExtension result.
The workaround for the error was found here: you need to put your element in resources. We get this:
XAML, modified according to the recommendations
<ListBox Name="ProcedureList" ItemsSource="{Binding Path=ProceduresView.View}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Name="ProcedurePanel" PreviewMouseDown="ProcedurePanel_OnPreviewMouseDown">
<DockPanel Width="{c:Binding ElementName=MainPanel, Path=Width-40}">
<!--<TextBlock Name="MainText" TextWrapping="Wrap" FontSize="16" Text="{Binding Path=title}" HorizontalAlignment="Left" />-->
<htb:HighlightTextBlock Name="MainText" TextWrapping="Wrap" FontSize="16"
Text="{Binding Path=title}" HorizontalAlignment="Left">
<htb:HighlightTextBlock.Resources>
<htb:HighlightRule x:Key="HR"
IgnoreCase="{Binding IgnoreCase, Source={StaticResource SourceVm}}"
HightlightedText="{Binding Path=DataContext.title, Source={x:Reference MainText}, Converter={StaticResource getFilter}}">
<htb:HighlightRule.Highlights>
<htb:HighlightBackgroung Brush="Yellow"/>
</htb:HighlightRule.Highlights>
</htb:HighlightRule>
</htb:HighlightTextBlock.Resources>
<htb:HighlightTextBlock.HighlightRules>
<htb:HighlightRulesCollection>
<StaticResource ResourceKey="HR"/>
</htb:HighlightRulesCollection>
</htb:HighlightTextBlock.HighlightRules>
</htb:HighlightTextBlock>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I was given advice on the restructuring of XAML, through resources, this partially solved the problem (I successfully got the title text in the converter), but the element ceased to perform its functions (allocation) During the discussion, it was suggested that the component itself should be finalized
#iRumba: In theory, the whole trick should not be necessary if you put
the HighlighRule collection (also) in a visual tree. Then the
DataContext will be automatically inherited and on idea the binding
through ElementName too will work.
#iRumba: I do not remember exactly. It seems, it is necessary to
specify to add all HighlightRule as LogicalChildren (for this purpose
on idea it is necessary to redefine protected internal override
IEnumerator LogicalChildren). This is a complicated, advanced
technique, yes.
Sorry for Google Translator
Found a solution
public class SearchHightlightTextBlock : TextBlock
{
public SearchHightlightTextBlock() : base() { }
public String SearchText
{
get { return (String)GetValue(SearchTextProperty); }
set { SetValue(SearchTextProperty, value); }
}
private static void OnDataChanged(DependencyObject source,
DependencyPropertyChangedEventArgs e)
{
TextBlock tb = (TextBlock)source;
if (tb.Text.Length == 0)
return;
string textUpper = tb.Text.ToUpper();
String toFind = ((String)e.NewValue).ToUpper();
int firstIndex = textUpper.IndexOf(toFind);
String firstStr = "";
String foundStr = "";
if (firstIndex != -1)
{
firstStr = tb.Text.Substring(0, firstIndex);
foundStr = tb.Text.Substring(firstIndex, toFind.Length);
}
String endStr = tb.Text.Substring(firstIndex + toFind.Length,
tb.Text.Length - (firstIndex + toFind.Length));
tb.Inlines.Clear();
tb.FontSize = 16;
var run = new Run();
run.Text = firstStr;
tb.Inlines.Add(run);
run = new Run();
run.Background = Brushes.Yellow;
run.Text = foundStr;
tb.Inlines.Add(run);
run = new Run();
run.Text = endStr;
tb.Inlines.Add(run);
}
public static readonly DependencyProperty SearchTextProperty =
DependencyProperty.Register("SearchText",
typeof(String),
typeof(SearchHightlightTextBlock),
new FrameworkPropertyMetadata(null, OnDataChanged));
}
Use
<parser:SearchHightlightTextBlock SearchText="{Binding Path=title, Converter={StaticResource getFilter}}" Text="{Binding title}"/>
i am using wpf tab control and setting the Icon and text in the tab header through style, i am able to set the text dynamically through getter and setter but can not able to set the image source. I tried to bind the image source through getter and setter but failed. Following is the style code in which i want to set the image source dynamically from the code behind.
-->
<Setter Property="HeaderTemplate" >
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!--<Image gif:ImageBehavior.AnimatedSource="{DynamicResource MyFillBrush}" Width="20" />-->
<Image gif:ImageBehavior.AnimatedSource="25.gif" Width="20" />
<Label Content="{Binding }"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
I know this is a bit old thread, but this is how you update the AnimatedSource from code:
var image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(value);
image.EndInit();
ImageBehavior.SetAnimatedSource(Imagereference, image);
The 'value' is the location of your gif file such as "25.gif".
The Imagereference is the Image control you want to update. Also ensure you have the namespace referenced: using WpfAnimatedGif;
Maybe you can use Binding, something like
private string _dynamicGif = "test.gif";
public string DynamicGif
{
get { return _dynamicGif; }
private set
{
_dynamicGif = value;
RaisePropertyChanged("DynamicGif");
}
}
and
<Image gif:ImageBehavior.AnimatedSource="{Binding DynamicGif, UpdateSourceTrigger=PropertyChanged}" Width="20" />
Or, if it doesn't work, you can use MediaElement instead of Image, it won't require WPF Animated GIF. It's also pretty simple to use:
private Uri _imgSource = new Uri("test.gif");
public Uri ImgSource
{
get { return _imgSource; }
private set
{
_imgSource = value;
RaisePropertyChanged("ImgSource");
}
}
and
<MediaElement x:Name="gifImg" LoadedBehavior="Play" Width="20" Source="{Binding ImgSource}"/>
Hope this helps.
I have a rather simple UserControl which I would like to extend with the DependencyProperty. The relevant code of the control is as follows:
public partial class CompassControl : UserControl
{
public static readonly DependencyProperty AngleProperty =
DependencyProperty.Register("Angle", typeof(Double), typeof(CompassControl),
new FrameworkPropertyMetadata( 0.0, FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnAngleChanged)));
private static void OnAngleChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
((CompassControl)target).SetImageAngle((Double)e.NewValue);
}
public CompassControl( )
{
InitializeComponent( );
}
public Double Angle
{
get { return (Double)GetValue(AngleProperty); }
set { SetValue(AngleProperty, value); }
}
This control is being used on a simple form; the relevant XAML as follows:
<DockPanel DockPanel.Dock="Bottom">
<DockPanel>
<TextBlock DockPanel.Dock="Left"
TextAlignment="Center" FontWeight="Bold" FontSize="12"
Padding="0,4,0,0" HorizontalAlignment="Left"
Height="22" Width="60" Margin="10,0,0,0"
Text="{Binding ElementName=scrollBarAngle, Path=Value}">
</TextBlock>
<ScrollBar DockPanel.Dock="Left" Name="scrollBarAngle" Orientation="Horizontal"
Height="22" Margin="10,0"
Maximum="360.0" Minimum="0.0" SmallChange="1.0" Value="0.0"
ValueChanged="scrollBarAngle_ValueChanged" />
</DockPanel>
</DockPanel>
<ctl:CompassControl DockPanel.Dock="Top" Name="compassControl"
Margin="5" Width="Auto" Height="Auto"
Angle="{Binding ElementName=scrollBarAngle, Path=Value}"
/>
</DockPanel>
The "Text" property of the TextBox and the "Angle" property of my control are bound to the "Value" property of the ScrollBar using the following binding:
"{Binding ElementName=scrollBarAngle, Path=Value}"
When I scroll the ScrollBar, the Text field is updated as expected, but the Angle does not change - the OnAngleChanged callback is not being called!
However if I directly change the Angle property in the ScrollBar's ValueChanged event everything works fine - the property got changed and the respective callback fired:
private void scrollBarAngle_ValueChanged( object sender, RoutedPropertyChangedEventArgs<double> e )
{
compassControl.Angle = e.NewValue;
}
Please help resolve this issue!
Thank you,
--Alex
My apologies - the problem was not in the code, but in the environment! I had several copies of VS2013 open, the project was open in two of them. Anyway, after reading Clemens comment indicating that my problem is not reproducible, I closed all instances of VS, then started the fresh instance, opened the project - and everything worked fine!
Thank you!
I am making a WP8 application with a lot of local content in my Assets folder. So I am using a JSON file stored in the a JSON folder.
I have been able to parse the JSON to C# very easily and now I am trying to display the data in a list. I had no problem with displaying the title but I am unable to display an image, even with the filename I am got.
My images are stored in "Assets/Content/mediaXXX.jpg";
ListViewModel :
public class ListViewModel
{
public string Title { get; set; }
public string Subtitle { get; set; }
public BitmapImage ListImage { get; set; }
}
XAML
<ListBox Margin="0,1,0,0"
Height="730"
x:Name="MainList">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Height="120"
Width="480">
<StackPanel Orientation="Horizontal">
<Image HorizontalAlignment="Left"
Source="{Binding ListImage}"
Margin="12"
Stretch="UniformToFill"
Width="130"/>
<Grid>
<TextBlock x:Name="ListItemTitle"
Text="{Binding Title}"/>
<TextBlock x:Name="ListItemSubTitle"
Text="{Binding Subtitle}"/>
</Grid>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And my C# page
BitmapImage image = new BitmapImage(new Uri(#"Assets/Content/" + photo.filename + ".jpg", UriKind.Relative);
l.ListImage = image;
Any idea?
Code should work. Only problems that might occur is your ListBox databinding is incorrectly defined.
I don't see any .ItemsSource = or ItemsSource={Binding some_collection}
Another thing is make sure that photo.filename is returning the correct file.
Set a string debug_string = "Assets/Content/" + photo.filename + ".jpg";
Make sure everything is correct.
Last thing is to make sure the files are actually in the Assets Folder inside the project and its
BuildAction is set to Content
like so
Using C#.Net 4.5, Visual Studio 2012 Ulti, WPF.
I've got some old win-forms code that i wanted to do in this new WPF app.
code is the following:
DataGridViewImageCell pNew = new DataGridViewImageCell();
ParetoGrid.Columns.Add(new DataGridViewImageColumn() { CellTemplate = pNew, FillWeight = 1, HeaderText = "pNew", Name = "pNew", Width = 30 });
ParetoGrid.Columns["pNew"].DisplayIndex = 18;
3 lines of code to add a column that can handle images. In WPF I've seen its a bit different. Do i need to add an "image column"? or does WPF columns support images? or is there another 3 liner solution that is simply different syntax?
Thanks for the help guys
See this answer:
Image Column in WPF DataGrid
<DataGridTemplateColumn Header="Image" Width="SizeToCells"
IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Image}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
To add a column in code after:
DataGridTextColumn textColumn1 = new DataGridTextColumn();
textColumn1.Header = "Your header";
textColumn1.Binding = new Binding("YourBindingField");
dg.Columns.Add(textColumn1);
Use DataGridTemplateColumn to add a custom column
See: How do I show image in wpf datagrid column programmatically?
Here is what I did.
Add a datatemplate in your datagrid with image control like this
<DataGridTemplateColumn Header="File Type" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Height="25" Width="50" Source="{Binding FileIcon}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
As you can see my I am binding Image with a property named "FileIcon" that is used in class Version like this
public class Version
{
public string FileIcon { get; set; }
}
Now only this you have to do is bind provide a path to "FileIcon" and update ItemSource of DataGrid like this
ObservableCollection<Version> items = new ObservableCollection<Version>();
items.Add(new Version()
{
FileIcon = "/AssemblyName;component/Images/eye.png",
});
YourDataGrid.ItemsSource = null;
YourDataGrid.ItemsSource = items;
Here is MainWindow.xaml's code just simple for better understanding
`
<Window x:Class="Pic_in_Datagrid.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:Pic_in_Datagrid"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid x:Name="dt1" ColumnWidth="*" AutoGenerateColumns="False">
</DataGrid>
</Grid>
</Window>
After it here is my MainWindow.xaml.cs's code for image or text for adding in datadrid dynamically...
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using System.Windows.Controls;
namespace Pic_in_Datagrid
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public StudentData stu_data { get; set; }
public MainWindow()
{
InitializeComponent();
stu_data = new StudentData();
List<StudentData> stu = new List<StudentData>();
stu.Add(new StudentData() { image = toBitmap(File.ReadAllBytes(#"D:\1.jpg")), stu_name = "abc" });
stu.Add(new StudentData() { image = toBitmap(File.ReadAllBytes(#"D:\1.jpg")), stu_name = "def" });
FrameworkElementFactory factory = new FrameworkElementFactory(typeof(System.Windows.Controls.Image));
Binding bind = new System.Windows.Data.Binding("image");//please keep "image" name as you have set in your class data member name
factory.SetValue(System.Windows.Controls.Image.SourceProperty, bind);
DataTemplate cellTemplate = new DataTemplate() { VisualTree = factory };
DataGridTemplateColumn imgCol = new DataGridTemplateColumn()
{
Header = "image", //this is upto you whatever you want to keep, this will be shown on column to represent the data for helping the user...
CellTemplate = cellTemplate
};
dt1.Columns.Add(imgCol);
dt1.Columns.Add(new DataGridTextColumn()
{
Header = "student name",
Binding = new Binding("stu_name") //please keep "stu_name" as you have set in class datamember name
});
dt1.ItemsSource = stu;
}
public static BitmapImage toBitmap(Byte[] value)
{
if (value != null && value is byte[])
{
byte[] ByteArray = value as byte[];
BitmapImage bmp = new BitmapImage();
bmp.BeginInit();
bmp.StreamSource = new MemoryStream(ByteArray);
bmp.EndInit();
return bmp;
}
return null;
}
}
public class StudentData
{
public BitmapImage image { get; set; }
public string stu_name { get; set; }
}
}
The above all code is taken from different resources... Thanks to them who developed and shared these codes...
You may try add Image to DataGridTextColumn via pattern bellow. You may sorting and copy to clipboard works well. Use your converter, or binding to your property.
<DataGridTextColumn Header="Level" IsReadOnly="True" Binding="{Binding Level,Converter={StaticResource LogLevelStringConverter}}" >
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Grid Background="{TemplateBinding Background}" >
<ContentPresenter VerticalAlignment="Center" Margin="20,0,0,0" HorizontalAlignment="Left" />
<Image Grid.Column="0" Width="18" Height="18" Source="{Binding Level,Converter={StaticResource LogLevelIconConverter}}" HorizontalAlignment="Left" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>