LinkButton doesn't work Silverlight - c#

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;
}

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();
}
}

Format CDATA Type from RSS with C# XDocument or XPath in WPF

I'm trying to format and get the image, text etc.. to give a good look and feel.
The XML is something like this:
xmlns:content="http://purl.org/rss/1.0/modules/content/"
And the content is:
<content:encoded>
<![CDATA[
<p><a href="http://i2.wp.com/geekytheory.com/wp-content/uploads/2014/03/Screen-Shot- 2013-11-11-at-11.38.50.png"><img class="size-full wp-image-7447 aligncenter" alt="Screen Shot 2013-11-11 at 11.38.50" src="http://i2.wp.com/geekytheory.com/wp- content/uploads/2014/03/Screen-Shot-2013-11-11-at-11.38.5
]]>
<![CDATA[
0.png?resize=788%2C644" data-recalc-dims="1" /></a></p> <p style="text-align: justify">
</p>]]>
< /content:encoded>
At first what I will get is the image or example: he is in content:encoded/p/a/img/src
the code that I try is:
private ObservableCollection<RssItem> ParseXmlString(string xmlString)
{
XDocument xmlDoc = XDocument.Parse(xmlString);
XNamespace xmns = #"http://purl.org/dc/elements/1.1/";
XNamespace xmnsContent = #"http://purl.org/rss/1.0/modules/content/";
var itemsList = xmlDoc.Descendants("item").Select(i => new RssItem()
{
Author = i.Element(xmns + "creator").Value,
Title = i.Element("title").Value,
Description = i.Element("description").Value,
Content = i.Element(xmnsContent + "encoded").Value,
Image = i.Element(xmnsContent + "encoded").XPathSelectElement("//p//a//img[#src]").Value,
Date = DateTime.Parse(i.Element("pubDate").Value)
}).ToList();
return new ObservableCollection<RssItem>(itemsList);
}
The Content = i.Element(xmnsContent + "encoded").Value give me all the content without formatting something like this:
And for exctract the image or some other element from the CData I get a error.
Image = i.Element(xmnsContent + "encoded").XPathSelectElement("//p//a//img[#src]").Value is giving error.
I tried this way too, but giving the same error.
Image = i.Element(xmnsContent+"encoded").Element("p").Element("a").Element("img").Attribute("src").Value
Thanks for all and greetings!!
Finally with a FlowDocumentScrollViewer an the XmlToXamlConverter I get the solution:
<FlowDocumentScrollViewer
Document="{Binding Content, Converter={StaticResource HtmlToFlowDocConverter}}"/>
After we need to add a Converter like:
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
var xaml = HtmlToXamlConverter.ConvertHtmlToXaml((string)value, true);
var flowDocument = XamlReader.Parse(xaml);
if (flowDocument is FlowDocument)
SubscribeToAllHyperlinks((FlowDocument)flowDocument);
return flowDocument;
}
private void SubscribeToAllHyperlinks(FlowDocument flowDocument)
{
var hyperlinks = GetVisuals(flowDocument).OfType<Hyperlink>();
foreach (var link in hyperlinks)
link.RequestNavigate += LinkRequestNavigate;
}
private static IEnumerable<DependencyObject> GetVisuals(DependencyObject root)
{
foreach (var child in
LogicalTreeHelper.GetChildren(root).OfType<DependencyObject>())
{
yield return child;
foreach (var descendants in GetVisuals(child))
yield return descendants;
}
}
private void LinkRequestNavigate(object sender,
System.Windows.Navigation.RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
}
Finally we will add the XmlToXamlConverter from here and another from here.
Another helpfull article for me was this.
Greetings!

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