I'm trying to implement a photo sharing application with two Android phones and a surface application using the toolkit for Windows Touch Beta. Therefore, I created a ScatterView called MainScatterView as basic Layout. Each time a user touches the screen, a Blob will be created in this MainScatterView. The Blob itself is a ScatterViewItem that contains a ScatterView named Blob. This Blob contains the photos of a specific album on the Android phone.
Dragging & Dropping photos between two blobs works well, but if I want to drop an item on the MainScatterView the dependant onDrop method is never called. My assumption is that this problem depends on the different Layers that a Blob ScatterView and the MainScatterView have, but that's only an assumption. Here's my XAML code:
<s:SurfaceWindow
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="http://schemas.microsoft.com/surface/2008"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="FotoSharing.SurfaceWindow1"
Width="1920" Height="1080" BorderThickness="5" BorderBrush="White" WindowStyle="None">
<s:SurfaceWindow.Resources>
<ImageBrush x:Key="WindowBackground" Stretch="None" Opacity="0.6" ImageSource="pack://application:,,,/Resources/WindowBackground.jpg"/>
</s:SurfaceWindow.Resources>
<s:SurfaceWindow.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="Black"/>
<GradientStop Color="#FFA784C8" Offset="1"/>
</LinearGradientBrush>
</s:SurfaceWindow.Background>
<s:ScatterView x:Name="MainScatterView" Margin="0" Width="1920" Height="1080" AllowDrop="True" s:SurfaceDragDrop.Drop="OnDrop" PreviewTouchDown="OnDragSourcePreviewTouchDown">
<s:ScatterViewItem x:Name="sviBlob1" Width="600" Height="600" Orientation="0" CanMove="False" CanRotate="False" CanScale="False" Visibility="Collapsed">
<Viewbox x:Name="ViewBoxBlob1">
<s:ScatterView x:Name="Blob1" Width="600" Height="600" AllowDrop="True" s:SurfaceDragDrop.Drop="OnDrop" PreviewTouchDown="OnDragSourcePreviewTouchDown">
<s:ScatterView.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FFA784C8" Offset="1"/>
</LinearGradientBrush>
</s:ScatterView.Background>
<s:ScatterViewItem x:Name="sviBlob1Header" Width="600" Height="40" CanRotate="False" CanMove="False" CanScale="False" Orientation="0" Center="300,20" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
<s:ScatterViewItem.Background>
<LinearGradientBrush EndPoint="0,0" StartPoint="0,1">
<GradientStop Color="#FFA4B4BD" Offset="0"/>
<GradientStop Color="#FF65438F" Offset="1"/>
</LinearGradientBrush>
</s:ScatterViewItem.Background>
<Canvas x:Name="Blob1Header" Height="40" Width="600">
<Image x:Name="Blob1NavigateLeft" Height="40" Width="50" Source="Icons\navigate_left_256.png" Canvas.Left="480" TouchDown="handleTouchDownNavigateLeft" Visibility="Hidden"/>
<Image x:Name="Blob1NavigateRight" Height="40" Width="50" Source="Icons\navigate_right_256.png" Canvas.Left="535" TouchDown="handleTouchDownNavigateRight" Visibility="Hidden"/>
<Image x:Name="Blob1ZoomIn" Height="40" Width="50" Source="Icons\zoom_in_128.png" Canvas.Left="294" TouchDown="handleTouchDownZoomIn"/>
<Image x:Name="Blob1ZoomOut" Height="40" Width="50" Source="Icons\zoom_out_128.png" Canvas.Left="360" TouchDown="handleTouchDownZoomOut"/>
<Image x:Name="Blob1Pin" Height="50" Width="50" Source="Icons\pin_black_128.png" Canvas.Left="480" TouchDown="handleTouchDownPin"/>
<Image x:Name="Blob1DragDrop" Height="40" Width="46" Source="Icons\dragdrop.png" Canvas.Left="430" TouchDown="handleTouchDownDragDrop"/>
<Image x:Name="Blob1Close" Height="40" Width="50" Source="Icons\delete_blob_128.png" Canvas.Left="535" TouchDown="handleTouchDownClose"/>
<Image x:Name="Blob1Album" Height="40" Width="50" Source="Icons\album_128.png"/>
<Label x:Name="Blob1AlbumName" Content="Label" Width="250" Height="40" Canvas.Left="52" FontSize="26.667" Canvas.Top="-4" FontWeight="Bold" FontStyle="Italic"/>
</Canvas></s:ScatterViewItem>
</s:ScatterView>
</Viewbox>
</s:ScatterViewItem>
<s:ScatterViewItem x:Name="sviBlob2" Width="600" Height="600" Orientation="0" CanMove="False" CanRotate="False" CanScale="False" Visibility="Collapsed">
<Viewbox x:Name="ViewBoxBlob2">
<s:ScatterView x:Name="Blob2" Width="600" Height="600" AllowDrop="True" s:SurfaceDragDrop.Drop="OnDrop" PreviewTouchDown="OnDragSourcePreviewTouchDown">
<s:ScatterView.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FFA784C8" Offset="1"/>
</LinearGradientBrush>
</s:ScatterView.Background>
<s:ScatterViewItem x:Name="sviBlob2Header" Width="600" Height="40" CanRotate="False" CanMove="False" CanScale="False" Orientation="0" Center="300,20" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
<s:ScatterViewItem.Background>
<LinearGradientBrush EndPoint="0,0" StartPoint="0,1">
<GradientStop Color="#FFA4B4BD" Offset="0"/>
<GradientStop Color="#FF65438F" Offset="1"/>
</LinearGradientBrush>
</s:ScatterViewItem.Background>
<Canvas x:Name="Blob2Header" Height="40" Width="600">
<Image x:Name="Blob2NavigateLeft" Height="40" Width="50" Source="Icons\navigate_left_256.png" Canvas.Left="480" TouchDown="handleTouchDownNavigateLeft" Visibility="Hidden"/>
<Image x:Name="Blob2NavigateRight" Height="40" Width="50" Source="Icons\navigate_right_256.png" Canvas.Left="535" TouchDown="handleTouchDownNavigateRight" Visibility="Hidden"/>
<Image x:Name="Blob2ZoomIn" Height="40" Width="50" Source="Icons\zoom_in_128.png" Canvas.Left="294" TouchDown="handleTouchDownZoomIn"/>
<Image x:Name="Blob2ZoomOut" Height="40" Width="50" Source="Icons\zoom_out_128.png" Canvas.Left="360" TouchDown="handleTouchDownZoomOut"/>
<Image x:Name="Blob2Pin" Height="50" Width="50" Source="Icons\pin_black_128.png" Canvas.Left="480" TouchDown="handleTouchDownPin"/>
<Image x:Name="Blob2DragDrop" Height="40" Width="46" Source="Icons\dragdrop.png" Canvas.Left="430" TouchDown="handleTouchDownDragDrop"/>
<Image x:Name="Blob2Close" Height="40" Width="50" Source="Icons\delete_blob_128.png" Canvas.Left="535" TouchDown="handleTouchDownClose"/>
<Image x:Name="Blob2Album" Height="40" Width="50" Source="Icons\album_128.png"/>
<Label x:Name="Blob2AlbumName" Content="Label" Width="250" Height="40" Canvas.Left="52" FontSize="26.667" Canvas.Top="-4" FontWeight="Bold" FontStyle="Italic"/>
</Canvas></s:ScatterViewItem>
</s:ScatterView>
</Viewbox>
</s:ScatterViewItem>
</s:ScatterView>
The two depending Methods onDrop and OnDragPreviewTouchDown look like this:
private void OnDragSourcePreviewTouchDown(object sender, TouchEventArgs e)
{
if (allowDragDrop == true)
{
if (e.OriginalSource is Image)
{
if ((e.OriginalSource as Image).Parent is ScatterViewItem) // prevent that image of Hederline is handled as foto
{
Image foto = (Image)e.OriginalSource;
string fotoID = (string)foto.DataContext;
ScatterViewItem draggedElement = (ScatterViewItem)(e.OriginalSource as Image).Parent;
double width = draggedElement.ActualWidth;
double height = draggedElement.ActualHeight;
double orientation = draggedElement.ActualOrientation;
ScatterViewItemDataContext context = (ScatterViewItemDataContext)draggedElement.DataContext;
context.originCenter = draggedElement.ActualCenter;
ScatterView dragSource = (ScatterView)draggedElement.Parent;
ScatterViewItem clonedDraggedElement = createScatterViewItemClone(width, height, orientation, context, fotoID);
// Create the cursor visual.
ContentControl cursorVisual = new ContentControl()
{
Content = clonedDraggedElement
};
// Create a list of input devices. Add the touches that
// are currently captured within the dragged element and
// the current touch (if it isn't already in the list).
List<InputDevice> devices = new List<InputDevice>();
devices.Add(e.TouchDevice);
foreach (TouchDevice touch in draggedElement.TouchesCapturedWithin)
{
if (touch != e.TouchDevice)
{
devices.Add(touch);
}
}
SurfaceDragCursor startDragOkay =
SurfaceDragDrop.BeginDragDrop(
dragSource, // The ScatterView object that the cursor is dragged out from.
draggedElement, // The ScatterViewItem object that is dragged from the drag source.
cursorVisual, // The visual element of the cursor.
draggedElement, // The data attached with the cursor.
devices, // The input devices that start dragging the cursor.
System.Windows.DragDropEffects.Move); // The allowed drag-and-drop effects of the operation.
// This if-clause causes, that the scatterviewitems are not deleted on the dragsource!
if (startDragOkay != null)
{
// Set e.Handled to true, otherwise the ScatterViewItem will capture the touch
// and cause the BeginDragDrop to fail.
e.Handled = true;
// Hide the ScatterViewItem.
draggedElement.Visibility = Visibility.Hidden;
}
}
}
}
}
private void OnDrop(object sender, SurfaceDragDropEventArgs e)
{
e.Handled = false;
Console.WriteLine(sender.ToString());
if (sender is ScatterView)
{
// Get drag source SV and drop SV
ScatterView dropScatterView = sender as ScatterView;
ScatterView dragSource = (ScatterView)e.Cursor.DragSource;
// Receive dragged Element from Cursor
ScatterViewItem draggedElement = (ScatterViewItem)e.Cursor.Data;
Image foto = (Image)draggedElement.Content;
// Get informations to clone dragged item
string fotoID = (string)foto.DataContext;
double width = draggedElement.ActualWidth;
double height = draggedElement.ActualHeight;
double orientation = draggedElement.ActualOrientation;
ScatterViewItemDataContext context = (ScatterViewItemDataContext)draggedElement.DataContext;
// Clone dragged item
ScatterViewItem clonedDraggedElement = createScatterViewItemClone(width, height, orientation, context, fotoID);
clonedDraggedElement.Center = e.Cursor.GetPosition(dropScatterView);
// Remove Item from Drag-Source
dragSource.Items.Remove(draggedElement);
// Item was droppeded in the same Blob
if (dragSource.Equals(dropScatterView))
{
dropScatterView.Items.Add(clonedDraggedElement);
// Update Center of Blob with Animation
PointAnimation pa = new PointAnimation();
pa.From = e.Cursor.GetPosition(dropScatterView);
pa.To = context.originCenter;
pa.Duration = TimeSpan.FromMilliseconds(500);
pa.FillBehavior = FillBehavior.HoldEnd;
clonedDraggedElement.BeginAnimation(ScatterViewItem.CenterProperty, pa);
}
else if (dropScatterView.Equals(MainScatterView) == false) // Foto was dropped to another Blob!
{
BlobInfo blobInfoDropSV = (BlobInfo)dropScatterView.DataContext;
// Add new fotoID to array of fotoIDs
blobInfoDropSV.fotoIDs.Add(fotoID);
// Add dragged foto to grid of Blob
FotoSampler fotoSampler = new FotoSampler();
Image dropFoto = fotoSampler.getImageByFotoID(fotoID);
ScatterViewItem sviToDrop = calculateFotoInGridPosition(blobInfoDropSV.fotoIDs.Count-1, dropFoto);
dropScatterView.Items.Add(sviToDrop);
PointAnimation pa = new PointAnimation();
pa.From = e.Cursor.GetPosition(dropScatterView);
pa.To = sviToDrop.Center;
pa.Duration = TimeSpan.FromMilliseconds(500);
pa.FillBehavior = FillBehavior.Stop;
sviToDrop.BeginAnimation(ScatterViewItem.CenterProperty, pa);
// refresh drag-Blob
BlobInfo blobInfoDragSV = (BlobInfo)dragSource.DataContext;
removeFotosFromBlob(dragSource);
int nbrOfFotosBeforeRefresh = blobInfoDragSV.fotoIDs.Count;
int idOfFotoToDelete = 0;
for (int i = 0; i < nbrOfFotosBeforeRefresh; i++) // remove FotoID from List of FotoIDs
{
if (blobInfoDragSV.fotoIDs[i].Equals(fotoID) == true)
{
idOfFotoToDelete = i;
}
}
blobInfoDragSV.fotoIDs.RemoveAt(idOfFotoToDelete); // delete draggedElement
createFotosInBlob(blobInfoDragSV.blobNbr, blobInfoDragSV.fotoIDs, blobInfoDragSV.zoomLevel); // calculate and order fotos again
// send Message mit Item to User
TcpClient client = new TcpClient(blobInfoDropSV.user.ip);
client.sendeNachricht("01#"+fotoID+"#");
}
}
}
I really tried a lot to solve this problem but nothing results in a comfortable solution.
I've recognized, that the ScatterView-Property Background has to be defined. Only if this property is set, events like the SurfaceDragDropEventArgs can be catched. Crazy!
Related
FlexLayout adjusts the spacing between the rows of content so the whole of its area is filled:
Can it be set to have no spacing between rows, or a fixed one? So that the rows would be packed to the top of the FlexLayout, and below there would be unused space? I have tried different settings (AlignItems, VerticalOptions, AlignContent) but couldn't achieve the desired result...
P.S.: the elements' size is fixed. These are added programmaticaly.
XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp3.ActivitiesPage">
<Grid RowDefinitions="50,*,75" ColumnDefinitions="200, *">
<ScrollView Grid.RowSpan="2" x:Name="ActScroll">
<VerticalStackLayout x:Name="Activities" Padding="5" />
</ScrollView>
<Frame Padding="5" Grid.Column="1">
<Entry x:Name="ActText" BackgroundColor="Grey" />
</Frame>
<FlexLayout Grid.Row="1" Grid.Column="1" x:Name="Picker" Direction="Row" Wrap="Wrap" Padding="5" />
<HorizontalStackLayout Grid.ColumnSpan="2" Grid.Row="2" Padding="5" >
<Button x:Name="btnAdd" Text="Add" Clicked="btnAdd_Clicked" Margin="10"/>
<Button x:Name="btnSave" Text="Save" Margin="10" IsEnabled="False" Clicked="btnSave_Clicked"/>
<Button x:Name="btnDelete" Text="Delete" Margin="10" IsEnabled="False" Clicked="btnDelete_Clicked"/>
</HorizontalStackLayout>
</Grid>
</ContentPage>
Code behind (fragment):
public ActivitiesPage()
{
InitializeComponent();
//color picker
var ActColors = new Color[]
{
Colors.DimGray,
Colors.DarkGray,
Colors.Linen,
Colors.AntiqueWhite,
Colors.PeachPuff,
Colors.Tan,
Colors.BurlyWood,
Colors.SandyBrown,
Colors.Peru,
Colors.Chocolate,
Colors.Firebrick,
Colors.DarkRed,
Colors.Brown,
Colors.IndianRed,
Colors.LightCoral,
Colors.LightPink,
Colors.PaleVioletRed,
Colors.HotPink,
Colors.DeepPink,
Colors.MediumVioletRed,
Colors.DarkMagenta,
Colors.DarkOrchid,
Colors.Orchid,
Colors.MediumPurple,
Colors.BlueViolet,
Colors.DarkSlateBlue,
Colors.RoyalBlue,
Colors.DodgerBlue,
Colors.DeepSkyBlue,
Colors.LightSkyBlue,
Colors.PaleTurquoise,
Colors.Turquoise,
Colors.MediumTurquoise,
Colors.Aqua,
Colors.LightSeaGreen,
Colors.SeaGreen,
Colors.DarkGreen,
Colors.ForestGreen,
Colors.LimeGreen,
Colors.PaleGreen,
Colors.YellowGreen,
Colors.Olive,
Colors.DarkGoldenrod,
Colors.DarkOrange,
Colors.Gold,
Colors.Orange,
Colors.OrangeRed,
Colors.Crimson,
Colors.DarkSalmon,
Colors.Coral,
};
foreach (var col in ActColors)
{
btn.Margin = 2;
btn.MinimumWidthRequest = 50;
btn.MaximumWidthRequest = 50;
btn.MaximumHeightRequest = 50;
btn.MinimumHeightRequest= 50;
btn.FontSize = 12;
btn.CornerRadius = 2;
Picker.Add(btn);
}
}
(this is why, source code goes a long way, when you post question)
Your FlexLayout is solved by:
AlignContent="Start" AlignItems="Start" Direction="Row" Wrap="Wrap"
There is nothing else that is needed to have what you want.
The interesting part is the code that is around this FlexLayout. How will you make sure that it gets its desired Width and Height? Easy way is to set its Width and Height request.
(Good way to write interface, is to set faint background of containers, to watch its borders when you make changes.)
Edit: Tested it:
<FlexLayout x:Name="flex" AlignContent="Start" AlignItems="Start" Direction="Row" Wrap="Wrap" BackgroundColor="AliceBlue" HorizontalOptions="FillAndExpand" HeightRequest="500">
And populated it:
for (int i = 0; i < 100; i++)
{
Button b = new Button();
b.WidthRequest = 25;
b.HeightRequest = 25;
b.Text = i.ToString();
flex.Add(b);
}
Everything is exactly like in your picture.
I have four columns in a datagrid and fourth column is templated and has textbox which is always editable.
What i am trying to achieve here is when a row selection changes the highlighted row's fourth cell which is editable and has textbox in it should get focus.
I am ok to get this done in codebehind or xaml.
Here is what i did:
<DataGrid Name="MyGrid" SelectionChanged="MyGrid_OnSelectionChanged" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Str1}" IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding Str2}" IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding Str3}" IsReadOnly="True"/>
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Str4}" GotFocus="UIElement_OnGotFocus" >
<TextBox.Style >
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=DataGridCell,AncestorLevel=1},Path=IsSelected}">
<Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
private void PopulateDummies()
{
int i = 0;
List<SomeDummy> dummies = new List<SomeDummy>();
while (i < 10)
{
dummies.Add(new SomeDummy
{
Str1 = string.Format("Str1:{0}", i),
Str2 = string.Format("Str2:{0}", i),
Str3 = string.Format("Str3:{0}", i),
Str4 = string.Format("Str4:{0}", i)
});
i++;
}
MyGrid.ItemsSource = dummies;
}
private void MyGrid_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void UIElement_OnGotFocus(object sender, RoutedEventArgs e)
{
var txtB = sender as TextBox;
txtB.Focus();
txtB.SelectAll();
}
Nothing seems to work. Not sure what is the reason. Can anyone help
The statement
txtB.Focus();
effectively replaces the DataGridCell by a TextEditory control. In order to do this, the view needs to be updated and therefore the UI-tread needs to run.
The SelectAll can not run until the editor is created, so run it as a separate Dispatcher-job and replace it with the following:
Application.Current.Dispatcher.BeginInvoke(new Action(() => {
txtB.SelectAll();
}), DispatcherPriority.Render);
This will do the trick and you don't need the SelctionChanged-event handler for this purpose.
I'm using Telerik RadGridView in my project (which essentially is a standart GridView).
This component has its own filtering functionality and I want to get advantage of it.
Filtering itself I am planning to do based on several combobox selected values. So if I got right idea of MVVM, I need to bind the combos to some ViewModel's properties. But here's a problem of how to pass these selected values back to View's component? how to make it refresh filtering as selected value change?
upd: I use SimpleMVVM framework.
XAML of MainWindow:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
......
DataContext="{Binding Source={StaticResource Locator}, Path=MainPageViewModel}">
<StackPanel Height="auto">
<telerik:RadMenu VerticalAlignment="Top">
......
</telerik:RadMenu>
<my:Expander VerticalAlignment="Top" HorizontalAlignment="Stretch" Height="auto" Width="auto"/>
<my:CustomerView Margin="0,0,0,0" VerticalAlignment="Top" HorizontalAlignment="Stretch" Height="auto" Width="auto"/>
</StackPanel>
XAML of expander:
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
...... >
<Grid Margin="10,10,0,10" Width="684" Height="97" VerticalAlignment="Top" HorizontalAlignment="Left" >
<telerik:RadExpander x:Name="radExpander" IsExpanded="True" HorizontalAlignment="Stretch" VerticalAlignment="Top" telerik:AnimationManager.IsAnimationEnabled="True" Margin="0,0,0,0" Grid.RowSpan="2">
<telerik:RadComboBox HorizontalAlignment="Left" Margin="244,-2,0,0" VerticalAlignment="Top" Width="154" Height="26"
ItemsSource="{Binding Path=AllLevels}" DisplayMemberPath="name" SelectedItem="{Binding SelectedEventLevel}"/>
.......
</Grid>
</telerik:RadExpander>
</Grid>
XAML of CustomerView:
<telerik1:RadGridView Name="EventList" .... ItemsSource="{Binding SportEventsList}" AutoGenerateColumns="False">
<telerik1:RadGridView.Columns>
.....
</telerik1:RadGridView.Columns>
</telerik1:RadGridView>
Snippet of Viewmodel's code:
private ObservableCollection<sportevent> _sportEventsList;
public ObservableCollection<sportevent> SportEventsList
{
get { return _sportEventsList; }
set
{
_sportEventsList = value;
NotifyPropertyChanged(vm => vm.SportEventsList);
}
}
Add the following properties to your VM:
private ObservableCollection<yourType> allLevels;
public ObservableCollection<yourType> AllLevels
{
get
{
return allLevels;
}
set
{
allLevels = value;
RaisePropertyChanged("AllLevels");
}
}
private yourType selectedEventLevel;
public yourTypeSelectedEventLevel
{
get
{
return selectedEventLevel;
}
set
{
selectedEventLevel = value;
RaisePropertyChanged("SelectedEventLevel");
}
}
I assume MainPageViewModel inherits SimpleViewModelBase
Below is my code :
<ext:GridPanel ID="gpMaster" runat="server" Title="List Of Messages" StripeRows="true"
AutoWidth="true" TrackMouseOver="true" Height="330" StoreID="stoMaster">
<ColumnModel ID="ColumnModel1" runat="server">
<Columns>
<ext:Column ColumnID="ID" Header="ID" Width="50" DataIndex="ID" Resizable="false"
MenuDisabled="true" Fixed="true" Align="Right" />
<ext:Column ColumnID="Subject" Header="Subject" DataIndex="Subject" Align="Right"
Width="300">
</ext:Column>
<ext:Column Header="Sender" DataIndex="Sender" Width="100" Align="Right">
</ext:Column>
<ext:Column Header="Receive Date" DataIndex="ReceiveDate" Align="Right" Width="100">
</ext:Column>
<ext:ImageCommandColumn Width="60" Align="Right" Css="text-align:center;">
<Commands>
<ext:ImageCommand CommandName="Edit" Icon="TableEdit" Text="Edit">
</ext:ImageCommand>
</Commands>
</ext:ImageCommandColumn>
<ext:ImageCommandColumn Width="60" Align="Center">
<Commands>
<ext:ImageCommand CommandName="Delete" Icon="Delete" Text="Delete">
</ext:ImageCommand>
</Commands>
</ext:ImageCommandColumn>
</Columns>
</ColumnModel>
<DirectEvents>
<Command OnEvent="Command">
<EventMask ShowMask="true"></EventMask>
<ExtraParams>
<ext:Parameter Name="id" Value="record.data.ID" Mode="Raw" />
<ext:Parameter Name="command" Value="command" Mode="Raw" />
</ExtraParams>
</Command>
</DirectEvents>
<SelectionModel>
<ext:RowSelectionModel ID="RowSelectionModel1" runat="server" SingleSelect="true" />
</SelectionModel>
<BottomBar>
<ext:PagingToolbar ID="PagingToolBar1" runat="server" PageSize="10" StoreID="stoMaster"
EmptyMsg=" " DisplayMsg=" " BeforePageText="Page" Cls="LTR" />
</BottomBar>
</ext:GridPanel>
protected void Command(object sender, DirectEventArgs e)
{
int messageID = int.Parse(e.ExtraParams["id"]);
string commandName = e.ExtraParams["command"];
switch (commandName)
{
case "Edit":
ShowEditElements(messageID);
break;
case "Delete":
DeleteMessage(messageID);
break;
}
}
void ShowEditElements(int messageID)
{
ExtNet.Msg.Alert("edit", "ShowEditElements");//Problem
}
void DeleteMessage(int messageID)
{
ExtNet.Msg.Alert("del", "DeleteMessage");//Problem
}
Everything is OK , But ExtNet.Msg.Alerts didn't shown !!!
What's wrong with it ?
how can I fix it ?
I had a problem in writing the code.
I had to change
ExtNet.Msg.Alert("edit", "ShowEditElements");
to
ExtNet.Msg.Alert("edit", "ShowEditElements").Show();
The problem was solved.
I have Employee Entity of northwind database and one of the field of this entity is "Photo" which is of type "Binary".
Now my question is how should i display the "Photo"fields in the Silverlight 4 datagrid so that i can view the employee photo?
What do i need todo in my WCF code or my ModelView Code?
My XAML code is given below:
<navigation:Page x:Class="NorthWind.SMS.UI.Views.EmployeeListing"
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"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="640" d:DesignHeight="480"
Title="EmployeeListing Page" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="50" MaxHeight="50" MinHeight="50" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Height="Auto" HorizontalAlignment="Left" Margin="5,5,0,0" Name="grid1" VerticalAlignment="Top" Width="Auto" />
<TextBlock Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="tbHeader" Text="Employee Listing" VerticalAlignment="Top" FontSize="14" FontFamily="Verdana" TextAlignment="Center" />
<sdk:DataGrid Grid.Row="1" ItemsSource="{Binding Path=Employees}" AutoGenerateColumns="False" Height="Auto" HorizontalAlignment="Left" Margin="5,5,0,0" Name="dgEmployee" VerticalAlignment="Top" Width="Auto" AlternatingRowBackground="{x:Null}">
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Header="Name">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding EmployeeName.TitleOfCourtesy}"></Run>
<Run Text="{Binding EmployeeName.FirstName}"></Run>
<Run Text="{Binding EmployeeName.LastName}"></Run></TextBlock>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTextColumn Binding="{Binding Path=Title}" Header="Title" />
<sdk:DataGridTextColumn Binding="{Binding Path=HireDate}" Header="HireDate" />
<sdk:DataGridTextColumn Binding="{Binding Path=BirthDate}" Header="DOB" />
<sdk:DataGridTextColumn Binding="{Binding Path=HomePhone}" Header="Phone" />
<sdk:DataGridTextColumn Binding="{Binding Path=City}" Header="City" />
<sdk:DataGridTextColumn Binding="{Binding Path=Region}" Header="Region" />
<sdk:DataGridTextColumn Binding="{Binding Path=Country}" Header="Country" />
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
</navigation:Page>
My ModelView Code is given below;
private void RefreshEmployees()
{
this.serviceClient.GetEmployeesListingCompleted += (s, e) =>
{
this.Employees = e.Result;
};
this.serviceClient.GetEmployeesListingAsync();
}
My WCF code that is getting the data is show below;
[OperationContract]
public IEnumerable<Employee> GetEmployeesListing()
{
using (var context = new NorthwindEntities())
{
//context.ContextOptions.LazyLoadingEnabled = false;
var result = context.Employees.ToList();
result.ForEach(e => context.Detach(e));
return result;
}
}
I found the answer to my question here is what i did;
Step 1:
WCF code modified to convert the Binary "Photo" field to Jpeg format.
Code is shown below;
[OperationContract]
public IEnumerable<Employee> GetEmployeesListing()
{
List<Employee> empList = new List<Employee>();
using (var context = new NorthwindEntities())
{
//context.ContextOptions.LazyLoadingEnabled = false;
var result = context.Employees.ToList();
result.ForEach(e => context.Detach(e));
//return result;
foreach (Employee emp in result)
{
Employee e = new Employee();
e.EmployeeName.TitleOfCourtesy = emp.EmployeeName.TitleOfCourtesy;
e.EmployeeName.FirstName = emp.EmployeeName.FirstName;
e.EmployeeName.LastName = emp.EmployeeName.LastName;
e.Title = emp.Title;
e.HireDate = emp.HireDate;
e.BirthDate = emp.BirthDate;
e.City = emp.City;
e.Region = emp.Region;
e.Country = emp.Country;
if (emp.Photo != null)
{
byte[] blob = emp.Photo;
using (MemoryStream ms = new MemoryStream())
{
ms.Write(blob, 78, blob.Length - 78);
Bitmap bm = (Bitmap)Image.FromStream(ms);
using (MemoryStream msJpg = new MemoryStream())
{
bm.Save(msJpg, ImageFormat.Jpeg);
e.Photo = msJpg.GetBuffer();
}
}
}
empList.Add(e);
}
return empList;
}
}
Step 2:
Create a Image Converter class implementing the IValueConverter interface in your Silverlight project.
Code is shown below;
public class ByteToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
byte[] pic = value as byte[];
if (value != null)
{
MemoryStream ms = new MemoryStream((byte[])value, false);
BitmapImage bmi = new BitmapImage();
bmi.SetSource(ms);
return bmi;
}
else return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Step 4
In the XAML file where you have your Data grid add a refernce of ByteToImageConverter class like this;
xmlns:src="clr-namespace:NorthWind.SMS.UI.Converters"
Step 5
Add a Static resource details in your XAML file like this;
<UserControl.Resources>
<src:ByteToImageConverter x:Key="ConvertToImage">
</src:ByteToImageConverter>
</UserControl.Resources>
Step 6
Update your datagrid image template like this;
<sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image x:Name="img1" Source ="{Binding Path=Photo, Converter={StaticResource ConvertToImage}}" Width="75" Height="75" Visibility="Visible"/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
This solution is working just fine for me.