Check if ImageSource is empty - c#

I'm using Binding to Image.SourceProperty from byte[] variable. At IValueConverter I check if value.Length > 0, if yes then I set source from it's value. Then I need to know, if it was set, so I can show or hide clear button. Image.Source always is not null. How can know, if it was set from byte[] array?
My code:
var bnd = new Binding
{
Mode = BindingMode.TwoWay,
Path = new PropertyPath("DataPath.Value"),
Converter = new ByteToImageConverter()
};
myImage.SetBinding(Image.SourceProperty, bnd);
public class ByteToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var val = value as byte[];
var bmp = new BitmapImage();
if (val.Length > 0) {
bmp.SetSource(new MemoryStream(val));
}
return bmp;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) {
return new byte[0];
}
var ms = new MemoryStream();
var bmp = new WriteableBitmap(value as BitmapSource);
bmp.SaveJpeg(ms, 150, 200, 0, 100);
return ms.ToArray();
}
}
Now I need code to check, if image source property is set:
// myImage.Source always != null even if there was no bmp.SetSource() call
var str = myImage.Source != null ? "Image is set" : "Image is empty";

something like that
if (((BitmapImage)myImage.Source).UriSource == null)
{
//Image is empty
}
or
var str = ((BitmapImage)myImage.Source).UriSource != null ? "Image is set" : "Image is empty";

Related

DataGridTemplateColumn: Problema con bind dictionary in combox part

I'm having a problem binding a dictionary in a combobox as part of a column in a DataGrid.
The dictionary changes on each line so I choose to use a Converter that changes from the value of another data column. The combo presents correctly the values ​​of the dictionary, but once an item is selected, the dictionary key is not applied (takes de value).
I show the code used and omit non-transcendent parts:
DataGridTemplateColumndatacol = new DataGridTemplateColumn();
datacol.Header = "Col1";
datacol.CanUserReorder = true;
datacol.SortMemberPath = "tablecol1";
//Part no edit
FrameworkElementFactory factory1 = new FrameworkElementFactory(typeof(TextBlock));
Binding bind1 = new Binding("tablecol1");
bind.Mode = BindingMode.OneWay;
factory1.SetValue(TextBlock.TextProperty, bind1);
DataTemplate cellTemplate1 = new DataTemplate();
cellTemplate1.VisualTree = factory1;
((DataGridTemplateColumn)datacol).CellTemplate = cellTemplate1;
//Part editable
FrameworkElementFactory factory2 = new FrameworkElementFactory(typeof(ComboBox));
Binding bind2 = new Binding("tablecol1");
bind2.Mode = BindingMode.TwoWay;
bind2.UpdateSourceTrigger = UpdateSourceTrigger.LostFocus;
Binding bindlist = new Binding(".");
bindlist.Mode = BindingMode.Default;
//Class converter
bindlist.Converter = new CustomDictionaryRowConverter();
factory2.SetValue(ComboBox.SelectedValuePathProperty, "Key");
factory2.SetValue(ComboBox.DisplayMemberPathProperty, "Value");
factory2.SetValue(ComboBox.ItemsSourceProperty, bindlist);
DataTemplate cellTemplate2 = new DataTemplate();
cellTemplate2.VisualTree = factory2;
((DataGridTemplateColumn)datacol).CellEditingTemplate = cellTemplate2;
The converter class returns a dictionary, I simplify the code:
public class CustomDictionaryRowConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null)
{
return new Dictionary<string, string>(
{ "key1", "Valor1"},
{ "key2", "Valor2"},
{ "key3", "Valor3"}
);
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
The combo has as bind the data column "tablecol1":
Binding bind2 = new Binding("tablecol1");
I hope you can help me. Thanks

How to set Datatemplate binding based on object type from code?

Don't ask why, but I have to create a WPF Listview in the business logic part of the code (the reason is I'm dealing with legacy code, thats why.)
Anyway, so far everything works, however, I want to add a checkbox column called "PermutationItem", where only some of the items have the corresponding property. In case a property doesn't have the property (= has the wrong type), I want to set the IsEnabled flag of the Checkbox to false automatically.
This is the code so far:
ListView lvPlatformList = new ListView()
{
Name = "MyListView"
};
lvPlatformList.BorderThickness = new Thickness(1);
lvPlatformList.Margin = new Thickness(0, HeightMargin, 25, HeightMargin);
var gridView = new GridView();
DataTemplate dtEnabled = new DataTemplate() { DataType = typeof(CheckBox) };
FrameworkElementFactory cbfEnabled = new FrameworkElementFactory(typeof(CheckBox));
cbfEnabled.SetBinding(CheckBox.IsCheckedProperty, new Binding("IsEnabled"));
dtEnabled.VisualTree = cbfEnabled;
gridView.Columns.Add(new GridViewColumn()
{
Header = "Enabled",
CellTemplate = dtEnabled
});
gridView.Columns.Add(new GridViewColumn()
{
Header = "Equipment Name",
DisplayMemberBinding = new Binding("Equipment.Name")
{
FallbackValue = "Empty Platform"
},
});
DataTemplate dtPermutationItem = new DataTemplate() { DataType = typeof(CheckBox) };
FrameworkElementFactory cbfPermutationItem = new FrameworkElementFactory(typeof(CheckBox));
cbfPermutationItem.SetBinding(CheckBox.IsCheckedProperty, new Binding("Equipment.IsPermutationItem.Value")
{
FallbackValue = false
});
cbfPermutationItem.SetBinding(CheckBox.IsEnabledProperty, /* What comes here?? */);
dtPermutationItem.VisualTree = cbfPermutationItem;
gridView.Columns.Add(new GridViewColumn()
{
Header = "PermutationItem",
CellTemplate = dtPermutationItem
});
lvPlatformList.View = gridView;
I know how I would solve this in XAML, but how can it be done here in the code?
I was able to solve it using a separate Binding with a new IValueConverter class. Instead of IsEnabled I used the Visibility property, but the same procedure is applicable to any property.
Here is the new Bindig:
cbfPermutationItem.SetBinding(CheckBox.VisibilityProperty, new Binding("Equipment")
{
Converter = new DataTypeToVisibilityConverter(),
ConverterParameter = typeof(MyTargetClass)
});
And here is the corresponding Visibility Converter:
public class DataTypeToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return Visibility.Hidden;
Type compareType = parameter as Type;
Type valueType = value.GetType();
if (compareType.IsAssignableFrom(valueType))
{
return Visibility.Visible;
}
else
{
return Visibility.Hidden;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
You can obviously put whatever you want into the converter, however a thing to note here is that IsAssignableFrom() function was needed in my case to work with inherited types.

Change background color of datagrid cell depending on object property

I create columns in an data grid via code-behind like this:
DataGridTextColumn dgtc1 = new DataGridTextColumn();
dgtc1.Header = "Feldname";
dgtc1.Binding = new Binding("FieldName");
dataGrid.Columns.Add(dgtc1);
DataGridTextColumn dgtc2 = new DataGridTextColumn();
dgtc2.Header = "Masterwert";
dgtc2.Binding = new Binding("MasterValue");
dataGrid.Columns.Add(dgtc2);
int counter = 0;
foreach (DBManager database in databases)
{
if (!database.IsMaster)
{
DataGridTextColumn dgtc = new DataGridTextColumn();
dgtc.Header = database.DisplayName;
dgtc.Binding = new Binding("LocationValues[" + counter + "]");
dataGrid.Columns.Add(dgtc);
counter++;
}
}
I want the cells to change their background color to a specific value depending on the items property "DeltaValues".
if(DeltaValues[i] == true)
//Change the background color to x
else
//Do nothing
Is there a Binding I could set for the columns from code-behind to achieve this behaviour?
Any ideas?
I not tested codes. I'm not sure DataGridCell.ContentProperty is correct property.:
if (!database.IsMaster)
{
DataGridTextColumn dgtc = new DataGridTextColumn();
dgtc.Header = database.DisplayName;
dgtc.Binding = new Binding("LocationValues[" + counter + "]");
Setter setter = new Setter();
setter.Property = Control.BackgroundProperty;
setter.Value = Brushes.Red;
Trigger trigger = new Trigger();
trigger.Property = DataGridCell.ContentProperty;
trigger.Value = true;
trigger.Setters.Add(setter);
dgtc.CellStyle.Triggers.Add(trigger);
dataGrid.Columns.Add(dgtc);
counter++;
}
or version with converter.
{
if (!database.IsMaster)
{
DataGridTextColumn dgtc = new DataGridTextColumn();
dgtc.Header = database.DisplayName;
dgtc.Binding = new Binding("LocationValues[" + counter + "]");
Converter converter = new Converter();
Binding binding = new Binding(DeltaValues[i]);
binding.Converter = converter;
dgtc.CellStyle.Setters.Add(new Setter(Control.BackgroundProperty, binding));
dataGrid.Columns.Add(dgtc);
counter++;
}
return this;
}
and very simple converter class:
public class Converter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((bool)value) return Brushes.Red;
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
new throw Exception();
}
}

LinkButton doesn't work Silverlight

I have a method that I call to create a link button. However the problem is that it passing the field name that the actual field to link button becasically giving me a dead link.
This is the method:
private static DataGridTemplateColumn CreateHyperlink(string fieldName)
{
DataGridTemplateColumn column = new DataGridTemplateColumn();
column.Header = "";
string link = #"http://www.amazon.com/gp/product/" + fieldName;
StringBuilder sb = new StringBuilder();
sb.Append("<DataTemplate ");
sb.Append("xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' ");
sb.Append("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' ");
sb.Append("xmlns:src='clr-namespace:Silverlight1.Classes;assembly=Silverlight1.Classes'>");
sb.Append("<HyperlinkButton ");
sb.Append("TargetName= '_blank' ");
sb.Append("Content = 'Link' ");
sb.Append("NavigateUri =" +"'"+ link +"'");
sb.Append(" />");
sb.Append("</DataTemplate>");
column.CellTemplate = (DataTemplate)XamlReader.Load(sb.ToString());
column.IsReadOnly = false;
return column;
}
Which is called by this
dgOrder.Columns.Add(CreateHyperlink("asin"));
Which is getting pulled from a WCF Silverlight enable data service.
How do I pass the content instead of field name?
You don't pass the content, you pass the field name but create a Binding. You will also need an implementation of a IValueConverter.
Lets start with an IValueConverter, you need something which take the string value of the "field" (by which I'm assuming you mean a Property of the objects bound to rows in the grid) and prefix it with #"http://www.amazon.com/gp/product/" to form a complete URL.
public class UrlPrefixConverter : IValueConverter
{
public string Prefix {get; set;}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null)
{
return new Uri(Prefix + value.ToString(), UriKind.Absolute);
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Place an instance of this in the App.xaml:-
<Application.Resources>
<local:UrlPrefixConverter Prefix="http://www.amazon.com/gp/product/" x:Key="AmazonPrefixConverter" />
</Application.Resources>
Now your create method can look like this:-
private static DataGridTemplateColumn CreateHyperlink(string fieldName)
{
DataGridTemplateColumn column = new DataGridTemplateColumn();
column.Header = "";
string template = #"<DataTemplate
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" >
<HyperlinkButton TargetName=""_blank"" Content=""Link""
NavigateUri=""{{Binding {0}, Converter={{StaticResource AmazonPrefixConverter}}}}"" />
</DataTemplate>";
column.CellTemplate = (DataTemplate)XamlReader.Load(String.Format(template, fieldName));
column.IsReadOnly = false;
return column;
}

Converter Binary to Image WPF;

Hi I'm trying to create a converter to Convert my images in a database ,datatype"Varbinary(Max)"
to populate my DataGrid in WPF but i have 2 error i show you the Converter:
public class BinaryToImageConverter : IValueConverter
{
public object Convert(object value, System.Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
Binary binaryData = value;// here there is the first error .How convert BinaryData to Object??
if (binaryData == null) {
return null;
}
byte[] buffer = binaryData.ToArray();
if (buffer.Length == 0) {
return null;
}
BitmapImage res = new BitmapImage();
res.BeginInit();
res.StreamSource = new System.IO.MemoryStream(buffer);
res.EndInit();
return res;
}
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
BitmapImage source = value;//How convert Bitmap to Object?
if (source == null) {
return null;
}
if ((source.StreamSource != null) && source.StreamSource.Length > 0) {
return GetBytesFromStream(source.StreamSource);
}
return null;
}
private Binary GetBytesFromStream(System.IO.Stream stream)
{
stream.Position = 0;
byte[] res = new byte[stream.Length + 1];
using (System.IO.BinaryReader reader = new System.IO.BinaryReader(stream)) {
reader.Read(res, 0, (int)stream.Length);
}
return new Binary(res);
}
}
Cab you advice me if it is right or there is a better way to do this?
Thanks for your help.
Have a good Day
If the value parameter does contain an object of the type BinaryData then you can just typecast it:
Binary binaryData = (Binary)value;
or
Binary binaryData = value as Binary;
It's probably better to do an is-null check on the value parameter before casting, rather than doing it after the cast, as you do now.

Categories