I am trying to run some source code that I downloaded from here
This is essentially an app that will allow users to manage contacts and calendar appointments etc.
I am currently experiencing 3 errors, all seemingly related...
CS1061 - UIImageView does not contain a definition for 'SetImage' and no extension method 'SetImage' accepting a first argument of type 'UIImageView' could be found (are you missing a using directive or an assembly reference?)
It seems that SetImage is not defined somewhere?
Would someone be able to tell me what i need to do to resolve the error. I post my code below...
using System;
using Foundation;
using UIKit;
using System.CodeDom.Compiler;
using MessageUI;
using Microsoft.Office365.OutlookServices;
using FiveMinuteMeeting.Shared.ViewModels;
using CoreGraphics;
using FiveMinuteMeeting.Shared;
namespace FiveMinuteMeeting.iOS
{
partial class ContactDetailViewController : UIViewController
{
public ContactDetailViewController(IntPtr handle)
: base(handle)
{
}
public DetailsViewModel ViewModel
{
get;
set;
}
UIBarButtonItem save;
public override void ViewDidLoad()
{
base.ViewDidLoad();
NavigationController.NavigationBar.BarStyle = UIBarStyle.Black;
save = new UIBarButtonItem(UIBarButtonSystemItem.Save,
async (sender, args) =>
{
ViewModel.FirstName = TextFirst.Text.Trim();
ViewModel.LastName = TextLast.Text.Trim();
ViewModel.Email = TextEmail.Text.Trim();
ViewModel.Phone = TextPhone.Text.Trim();
//BigTed.BTProgressHUD.Show("Saving contact...");
await ViewModel.SaveContact();
//BigTed.BTProgressHUD.Dismiss();
NavigationController.PopToRootViewController(true);
});
TextEmail.ShouldReturn += ShouldReturn;
TextFirst.ShouldReturn += ShouldReturn;
TextPhone.ShouldReturn += ShouldReturn;
TextLast.ShouldReturn += ShouldReturn;
TextEmail.ValueChanged += (sender, args) =>
{
ImagePhoto.SetImage(
url: new NSUrl(Gravatar.GetURL(TextEmail.Text, 172)),
placeholder: UIImage.FromBundle("missing.png")
);
};
var color = new CGColor(17.0F / 255.0F, 113.0F / 255.0F, 197.0F / 255F);
TextEmail.Layer.BorderColor = color;
TextFirst.Layer.BorderColor = color;
TextPhone.Layer.BorderColor = color;
TextLast.Layer.BorderColor = color;
ButtonCall.Clicked += (sender, args) => PlaceCall();
NSNotificationCenter.DefaultCenter.AddObserver
(UIKeyboard.DidShowNotification, KeyBoardUpNotification);
// Keyboard Down
NSNotificationCenter.DefaultCenter.AddObserver
(UIKeyboard.WillHideNotification, KeyBoardDownNotification);
double min = Math.Min((float)ImagePhoto.Frame.Width, (float)ImagePhoto.Frame.Height);
ImagePhoto.Layer.CornerRadius = (float)(min / 2.0);
ImagePhoto.Layer.MasksToBounds = false;
ImagePhoto.Layer.BorderColor = new CGColor(1, 1, 1);
ImagePhoto.Layer.BorderWidth = 3;
ImagePhoto.ClipsToBounds = true;
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
if (ViewModel == null)
{
ViewModel = new DetailsViewModel();
NavigationItem.RightBarButtonItem = save;
}
else
{
this.Title = ViewModel.FirstName;
TextEmail.Text = ViewModel.Email;
TextFirst.Text = ViewModel.FirstName;
TextLast.Text = ViewModel.LastName;
TextPhone.Text = ViewModel.Phone;
ImagePhoto.SetImage(
url: new NSUrl(Gravatar.GetURL(ViewModel.Contact.EmailAddresses[0].Address, 172)),
placeholder: UIImage.FromBundle("missing.png")
);
NavigationItem.RightBarButtonItem = null;
}
}
private bool ShouldReturn(UITextField field)
{
field.ResignFirstResponder();
return true;
}
private void PlaceCall()
{
var alertPrompt = new UIAlertView("Dial Number?",
"Do you want to call " + TextPhone.Text + "?",
null, "No", "Yes");
alertPrompt.Dismissed += (sender, e) =>
{
if ((int)e.ButtonIndex >= (int)alertPrompt.FirstOtherButtonIndex)
{
var url = new NSUrl("tel:" + TextPhone.Text);
if (!UIApplication.SharedApplication.OpenUrl(url))
{
var av = new UIAlertView("Not supported",
"Scheme 'tel:' is not supported on this device",
null,
"OK",
null);
av.Show();
}
else
{
UIApplication.SharedApplication.OpenUrl(url);
}
}
};
alertPrompt.Show();
}
/*private async void SendEmail()
{
var mailController = new MFMailComposeViewController();
mailController.SetToRecipients(new string[] { TextEmail.Text });
mailController.SetSubject("5 Minute Meeting");
mailController.SetMessageBody("We are having a 5 minute stand up tomorrow at this time! Check your calendar.", false);
mailController.Finished += (object s, MFComposeResultEventArgs args) =>
{
Console.WriteLine(args.Result.ToString());
args.Controller.DismissViewController(true, (Action)null);
};
PresentViewControllerAsync(mailController, true);
}*/
public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender)
{
switch(segue.Identifier)
{
case "email":
{
var vc = segue.DestinationViewController as SendEmailViewController;
vc.ViewModel.FirstName = ViewModel.FirstName;
vc.ViewModel.LastName = ViewModel.LastName;
vc.ViewModel.Email = ViewModel.Email;
}
break;
case "meeting":
{
var vc = segue.DestinationViewController as NewEventDurationViewController;
vc.ViewModel.FirstName = ViewModel.FirstName;
vc.ViewModel.LastName = ViewModel.LastName;
vc.ViewModel.Email = ViewModel.Email;
}
break;
}
}
#region Keyboard
private UIView activeview; // Controller that activated the keyboard
private float scrollamount; // amount to scroll
private float bottom; // bottom point
private const float Offset = 68.0f; // extra offset
private bool moveViewUp; // which direction are we moving
private void KeyBoardDownNotification(NSNotification notification)
{
if (moveViewUp) { ScrollTheView(false); }
}
private void ScrollTheView(bool move)
{
// scroll the view up or down
UIView.BeginAnimations(string.Empty, System.IntPtr.Zero);
UIView.SetAnimationDuration(0.3);
CGRect frame = (CGRect)View.Frame;
if (move)
{
frame.Y -= scrollamount;
}
else
{
frame.Y += scrollamount;
scrollamount = 0;
}
View.Frame = frame;
UIView.CommitAnimations();
}
private void KeyBoardUpNotification(NSNotification notification)
{
// get the keyboard size
var r = (CGRect)UIKeyboard.FrameBeginFromNotification((NSNotification)notification);
// Find what opened the keyboard
foreach (UIView view in this.View.Subviews)
{
if (view.IsFirstResponder)
activeview = view;
}
// Bottom of the controller = initial position + height + offset
bottom = ((float)activeview.Frame.Y + (float)activeview.Frame.Height + Offset);
// Calculate how far we need to scroll
scrollamount = ((float)r.Height - ((float)View.Frame.Size.Height - bottom));
// Perform the scrolling
if (scrollamount > 0)
{
moveViewUp = true;
ScrollTheView(moveViewUp);
}
else
{
moveViewUp = false;
}
}
#endregion
}
}
I am very new to Xamarin & app development and I just wanted to run this because it is a very similar project to one that I am creating.
Thanks for your help
SetImage is a extension method contained in Xamarin.SDWebImage. Ensure, that you have restored all nuget packages or have installed it via
Install-Package Xamarin.SDWebImage
see: https://www.nuget.org/packages/Xamarin.SDWebImage/
Here a explanation of the error.
https://msdn.microsoft.com/en-us/library/bb383961.aspx
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
CS1061 - UIImageView does not contain a definition for 'SetImage' and no extension method 'SetImage' accepting a first argument of type 'UIImageView' could be found (are you missing a using directive or an assembly reference?)
In your code I don't watch a declaration of ImagePhoto check right click goto definition. And verify that for imagePhoto exist a method setImage ImagePhoto I'm asumming that is object of type UIImage
ImagePhoto.SetImage(
url: new NSUrl(Gravatar.GetURL(TextEmail.Text, 172)),
placeholder: UIImage.FromBundle("missing.png")
);
Related
I use WebSocketSharp to write a client, in Start I add the ChangeColor method to the OnMessage event, and the method is executed but not to the end, it does not change the color of the object, although it should. I tried to call the method in Update on button click and it worked correctly. What is the problem?
The server sends correct data, I checked
WebSocket ws;
private Renderer objectRenderer;
private Color matColor;
private string reciveData;
private void Start()
{
objectRenderer = GetComponent<Renderer>();
ws = new WebSocket("ws://127.0.0.1:8080");
ws.Connect();
ws.OnMessage += (sender, e) =>
{
reciveData = e.Data;
ChangeColor(e.Data); // its dosent work!
};
}
void Update()
{
if (ws == null)
return;
// its work
// if (Input.GetKeyDown(KeyCode.Space))
// {
// ChangeColor(reciveData);
// objectRenderer.material.color = matColor;
// }
}
public void ChangeColor(string data)
{
string[] colors = data.Split(',');
matColor = new Color()
{
r = float.Parse(colors[0]) / 255.0f,
g = float.Parse(colors[1]) / 255.0f,
b = float.Parse(colors[2]) / 255.0f,
a = float.Parse(colors[3]) / 255.0f
};
objectRenderer.material.color = matColor;
}
It does not work, because the WebSocketSharp callbacks run on a worker thread. Unity does not allow to interact with your objectRenderer in any other thread than the main thread.
You can cache the data as you did and process it in update method (which is called in main thread).
Use a boolean to tell the Update method to call your ChangeColour method.
WebSocket ws;
private Renderer objectRenderer;
private Color matColor;
private string reciveData;
private bool newDataToBeProcessed;
private void Start()
{
objectRenderer = GetComponent<Renderer>();
ws = new WebSocket("ws://127.0.0.1:8080");
ws.Connect();
ws.OnMessage += (sender, e) =>
{
reciveData = e.Data;
newDataToBeProcessed = true;
};
}
void Update()
{
if (ws == null)
return;
if (newDataToBeProcessed == true)
{
newDataToBeProcessed = false;
ChangeColor(reciveData);
objectRenderer.material.color = matColor;
}
}
public void ChangeColor(string data)
{
string[] colors = data.Split(',');
matColor = new Color()
{
r = float.Parse(colors[0]) / 255.0f,
g = float.Parse(colors[1]) / 255.0f,
b = float.Parse(colors[2]) / 255.0f,
a = float.Parse(colors[3]) / 255.0f
};
objectRenderer.material.color = matColor;
}
I have created an app using Xamarin to help watching movies online. It shows the subtitles on top of all other windows. This has been done using the NSPanel, as it was the only way to make it work on MacOS Mojave.
The app works well. Now I want to improve the app by making NSPanel respond to the keyboard events, so I can control the app by using the keyboard for pausing, playing, going backward or going forward.
How do I get keyboard events in the topmost NSPanel?
I tried to use this code:
NSEvent.AddLocalMonitorForEventsMatchingMask(NSEventMask.KeyDown, KeyboardEventHandler);
private static NSEvent KeyboardEventHandler(NSEvent keyEvent)
{
// handle key down events here
return (keyEvent);
}
But it only works when the app is not in the full-screen mode.
The full SubtitlesViewer-MACOS project can be found here.
Here is the part of the code that creates the panel:
public override void ViewWillAppear()
{
base.ViewWillAppear();
SetupView();
}
private void SetupView()
{
var screenRes = screenResolution();
int PANEL_HEIGHT = 200;
subtitlesPanel = new NSPanel
(
new CoreGraphics.CGRect(40, 50, screenRes.Width - 80, PANEL_HEIGHT),
NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Miniaturizable | NSWindowStyle.DocModal,
NSBackingStore.Buffered, true
)
{
BackgroundColor = NSColor.FromCalibratedRgba(0, 0, 0, 0.0f),
ReleasedWhenClosed = true,
HidesOnDeactivate = false,
FloatingPanel = true,
StyleMask = NSWindowStyle.NonactivatingPanel,
Level = NSWindowLevel.MainMenu - 1,
IsMovable = true,
CollectionBehavior = NSWindowCollectionBehavior.CanJoinAllSpaces |
NSWindowCollectionBehavior.FullScreenAuxiliary
};
subtitlesPanel.OrderFront(null);
subtitleTextButton = new NSButton(new CoreGraphics.CGRect(40, 0, screenRes.Width - 120, PANEL_HEIGHT-30))
{
Title = "",
WantsLayer = true
};
subtitleTextButton.Layer.BackgroundColor = NSColor.Clear.CGColor;
subtitleTextField = new NSTextField(new CoreGraphics.CGRect(40, 0, screenRes.Width - 120, PANEL_HEIGHT-30))
{
Alignment = NSTextAlignment.Center
};
subtitleTextField.Cell.Alignment = NSTextAlignment.Center;
forwardButton = new NSButton(new CoreGraphics.CGRect(0, 0, 40, 30));
forwardButton.Title = ">>";
forwardButton.Activated += (object sender, EventArgs e) => {
subtitlesProvider.Forward();
};
backButton = new NSButton(new CoreGraphics.CGRect(0, 30, 40, 30));
backButton.Title = "<<";
backButton.Activated += (object sender, EventArgs e) => {
subtitlesProvider.Back();
};
startStopButton = new NSButton(new CoreGraphics.CGRect(0, 60, 40, 30));
startStopButton.Title = "Play";
startStopButton.Activated += (object sender, EventArgs e) => {
subtitlesProvider.StartStop(subtitlesProvider.Playing);
};
subtitlesPanel.ContentView.AddSubview(subtitleTextButton, NSWindowOrderingMode.Below, null);
subtitlesPanel.ContentView.AddSubview(subtitleTextField, NSWindowOrderingMode.Below, null);
subtitlesPanel.ContentView.AddSubview(forwardButton, NSWindowOrderingMode.Below, null);
subtitlesPanel.ContentView.AddSubview(backButton, NSWindowOrderingMode.Below, null);
subtitlesPanel.ContentView.AddSubview(startStopButton, NSWindowOrderingMode.Below, null);
SetupSubtitlesProvider();
}
Please kindly advice what else should I try to make it work.
I have found the solution here:
keyDown not being called
This is my implementation of NSPanelExt class to handle the keys.
public class NSPanelExt : NSPanel
{
public KeyPressedHandler KeyPressed;
public delegate void KeyPressedHandler(KeyCodeEventArgs e);
public NSPanelExt(CGRect contentRect, NSWindowStyle aStyle, NSBackingStore bufferingType, bool deferCreation) : base(contentRect, aStyle, bufferingType, deferCreation)
{
}
public override bool CanBecomeMainWindow => true;
public override bool CanBecomeKeyWindow => true;
public override bool AcceptsFirstResponder()
{
return true;
}
public override void KeyDown(NSEvent theEvent)
{
// this function is never called
KeyPressed?.Invoke(new KeyCodeEventArgs { Key = GetKeyCode(theEvent.KeyCode) });
}
private KeyCode GetKeyCode(ushort keyCode)
{
KeyCode result = KeyCode.Unknown;
switch (keyCode)
{
case 123:
result = KeyCode.Left;
break;
case 49:
result = KeyCode.Space;
break;
case 124:
result = KeyCode.Right;
break;
case 53:
result = KeyCode.Esc;
break;
}
return result;
}
I have also updated the ViewController to keep NSPanel always active.
public partial class ViewController : NSViewController
{
// ...
private NSButton startStopButton;
Timer _timer = new Timer();
private void SetupView()
{
// ...
subtitlesPanel.KeyPressed += SubtitlesPanel_KeyPressed;
// ...
IntializeKeepWindowFocusedTimer();
}
void SubtitlesPanel_KeyPressed(KeyCodeEventArgs e)
{
switch(e.Key)
{
case KeyCode.Left:
backButton.PerformClick(this);
break;
case KeyCode.Right:
forwardButton.PerformClick(this);
break;
case KeyCode.Space:
startStopButton.PerformClick(this);
break;
case KeyCode.Esc:
_timer.Stop();
break;
}
}
private void IntializeKeepWindowFocusedTimer()
{
_timer.Interval = 200; //in milliseconds
_timer.Elapsed += Timer_Elapsed;;
_timer.AutoReset = true;
_timer.Enabled = true;
}
void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
NSApplication.SharedApplication.BeginInvokeOnMainThread(() =>
{
subtitlesPanel.MakeKeyWindow();
if (SetSubtitleNeeded)
{
subtitlesProvider.SetSubTitle(0);
startStopButton.Title = "Stop";
SetSubtitleNeeded = false;
_timer.Interval = 5000;
}
});
}
private bool SetSubtitleNeeded = false;
partial void ClickedButton(NSObject sender)
{
_timer.Stop();
var nsUrl = subtitleFileSelector.GetFile();
if (nsUrl == null)
return;
fileName = nsUrl.Path;
subtitlesProvider.ReadFromFile(fileName);
SetSubtitleNeeded = true;
_timer.Start();
}
I have the following test code running on my phone. It shows a circle on the map where my GeoFence is. If I walk outside of the fence, then back in then backout the events are never firing. I have no idea what Im missing:
using MonoTouch;
using CoreLocation;
using MapKit;
using System.Drawing;
using CoreGraphics;
namespace GeoFencingTest
{
public class GeoFencingController : UIViewController
{
UIWindow Parent;
CustomMapView mapView;
CLLocationManager locMgr = new CLLocationManager ();
UITextView textview;
UIButton button;
CLCircularRegion region;
CLLocationCoordinate2D FenceCenter;
public GeoFencingController (UIWindow parent)
{
var radius = 25;
FenceCenter = new CLLocationCoordinate2D (33.8399522334765, -84.3729872355209);
Parent = parent;
View = new UIView (new RectangleF ((float)Parent.Bounds.Left, (float)Parent.Bounds.Top, (float)Parent.Bounds.Width, (float)Parent.Bounds.Height));
parent.AddSubview (View);
locMgr.RequestWhenInUseAuthorization ();
locMgr.DesiredAccuracy = 5;
locMgr.StartUpdatingLocation ();
region = new CLCircularRegion (FenceCenter, radius, "TPM");
locMgr.StartMonitoring (region);
mapView = new CustomMapView ();
mapView.Frame = new RectangleF ((float)Parent.Bounds.Left + 20, (float)55, (float)Parent.Bounds.Width - 40, (float)Parent.Bounds.Height - 80);
mapView.ShowsUserLocation = true;
mapView.UserInteractionEnabled = true;
mapView.MapType = MKMapType.Hybrid;
mapView.ZoomEnabled = true;
mapView.ScrollEnabled = true;
mapView.UserTrackingMode = MKUserTrackingMode.Follow;
mapView.Delegate = new MapDelegate ();
mapView.CenterCoordinate = FenceCenter;
View.AddSubview (mapView);
var circleOverlay = MKCircle.Circle (new CLLocationCoordinate2D (FenceCenter.Latitude, FenceCenter.Longitude), radius);
mapView.AddOverlay (circleOverlay);
textview = new UITextView (new RectangleF (0, 20, 190, 50));
View.AddSubview (textview);
if (CLLocationManager.IsMonitoringAvailable (typeof(CLCircularRegion))) {
locMgr.DidStartMonitoringForRegion += (o, e) => {
textview.Text = "Now monitoring region " + e.Region.ToString ();
};
locMgr.RegionEntered += (o, e) => {
textview.Text = "Just entered " + e.Region.ToString ();
};
locMgr.RegionLeft += (o, e) => {
textview.Text = "Just left " + e.Region.ToString ();
};
} else {
textview.Text = "This app requires region monitoring, which is unavailable on this device";
}
}
public class MapDelegate : MKMapViewDelegate
{
public override MKOverlayView GetViewForOverlay (MKMapView mapView, NSObject overlay)
{
// return a view for the polygon
MKCircle circle = overlay as MKCircle;
MKCircleView circleView = new MKCircleView (circle);
circleView.FillColor = UIColor.Yellow;
circleView.Alpha = 0.5f;
circleView.LineWidth = 10;
circleView.StrokeColor = UIColor.Red;
return circleView;
}
}
public class CustomMapView : MKMapView
{
public override void TouchesBegan (NSSet touches, UIEvent evt)
{
base.TouchesBegan (touches, evt);
UITouch touch = touches.AnyObject as UITouch;
CGPoint pointInView = touch.LocationInView (this);
CLLocationCoordinate2D touchCoordinates = base.ConvertPoint (pointInView, this);
MKMapPoint mapPoint = MKMapPoint.FromCoordinate (touchCoordinates);
Console.WriteLine ("LAT: " + touchCoordinates.Latitude);
Console.WriteLine ("LON: " + touchCoordinates.Longitude);
}
}
}
}
You may want to try setting up your event handlers before calling StartMonitoring instead of after.
I have worked on titanium in past and it was very simple to use the paging control there. Just begun Xamarin iOS development and got stuck with this paging control. Not sure how to use it. I found an example here. It worked fine. My question is ,is the UIPageControl Useless ? I read it here that it is so. Does Xamarin have any control which could work like Titanium's Scrollable View ? Please suggest any better method than the code below .
Here's the code
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
createAndAddViewsToPagerControl ();
}
void createAndAddViewsToPagerControl ()
{
try {
int pageCount = PagerControlMain.Pages;
Console.WriteLine ("Pages Count in Page Control" + pageCount);
List<UIColor> _colList = new List<UIColor> {
UIColor.Red,
UIColor.Green,
UIColor.Blue,
UIColor.Yellow
};
int i = 0;
for (i = 0; i < pageCount; i++) {
UILabel label = new UILabel ();
RectangleF rectangle = new RectangleF ();
rectangle.X = (this.PagerScrollView.Frame.Width * i) + 50;
rectangle.Y = 0;
rectangle.Size = this.PagerScrollView.Frame.Size;
label.Frame = rectangle;
label.Text = i.ToString ();
label.TextColor = _colList [i];
this.PagerScrollView.AddSubview (label);
}
this.PagerControlMain.Pages = pageCount;
PagerScrollView.BackgroundColor = UIColor.Gray;
PagerScrollView.ContentSize = new SizeF (PagerScrollView.Frame.Width * i, PagerScrollView.Frame.Height);
this.PagerScrollView.Scrolled += ScrolledEvent;
} catch (Exception ex) {
Console.WriteLine ("Exception in PagerControl : " + ex);
}
}
private void ScrolledEvent (object sender, EventArgs e)
{
this.PagerControlMain.CurrentPage =
(int)System.Math.Floor (this.PagerScrollView.ContentOffset.X
/ this.PagerScrollView.Frame.Size.Width);
Console.WriteLine ("Scroll Event Fired");
}
partial void PagerControlMain_ValueChanged (UIPageControl sender)
{
Console.WriteLine ("Current Page " + sender.CurrentPage);
//throw new NotImplementedException ();
}
Is this what you want?
Xamarin: UIPageControl and UIScrollView for iOS homescreen look
you should add this in your createAndAddViewsToPagerControl () method:
PagerScrollView.ScrollEnabled = true;
PagerScrollView.PagingEnabled = true;
I'm using MonoDevelop tool.
I want to make program like below with GTK#;
1. User drags file to program's listView, tableView or whatever
2. Dragged file's list is printed on the program's window
But I'm almost new to GTK# and find the way how to drag and drop,
so I searched information about it and found this link like below.
http://developer.gnome.org/gtkmm-tutorial/3.0/sec-dnd-example.html.en
This is the code I tried to make program link suggested
(This link explains drag and drop in C++ and I had to make it the way like C#)
using Gtk;
using System;
using System.Collections;
using System.Collections.Generic;
namespace DragAndDrop
{
public class SharpApp: Window
{
Button btnDrag;
Label lblDrop;
HBox hbox;
public SharpApp (): base("Title")
{
btnDrag = new Button("Drag Here");
lblDrop = new Label("Drop Here");
hbox = new HBox();
SetDefaultSize(250,200);
SetPosition (Gtk.WindowPosition.Center);
DeleteEvent += (o, args) => Application.Quit ();
// Targets
List<TargetEntry> list
= new List<TargetEntry> ();
list.Add (new TargetEntry
("STRING", TargetFlags.Widget, 0));
list.Add (new TargetEntry
("text/plain", TargetFlags.Widget, 0));
// Drag site -----
// Make btnDrag a DnD drag source:
TargetEntry[] entries = list.ToArray();
TargetEntry[] se = new TargetEntry[] {entries[0]};
Drag.SourceSet (btnDrag, Gdk.ModifierType.ModifierMask,
se, Gdk.DragAction.Copy);
// Connect signals
btnDrag.DragDataGet += delegate
(object o, DragDataGetArgs args) {
Console.WriteLine ("Test");
OnDragDataGet(args.Context,
args.SelectionData,
args.Info,
args.Time);
};
hbox.PackStart (btnDrag);
// Drop site -----
// Make lblDrop a DnD drop destination:
TargetEntry[] de = new TargetEntry[] {entries[1]};
Drag.DestSet (lblDrop, DestDefaults.Drop,
de, Gdk.DragAction.Copy);
// Connect signals
lblDrop.DragDataReceived += delegate
(object o, DragDataReceivedArgs args) {
Console.WriteLine ("Test");
OnDragDataReceived(args.Context,
args.X,
args.Y,
args.SelectionData,
args.Info,
args.Time);
};
// hbox
hbox.PackStart (lblDrop);
Add (hbox);
ShowAll ();
}
// event handlers
protected override void OnDragDataGet
(Gdk.DragContext context, SelectionData sdata,
uint info, uint time)
{
Console.WriteLine ("OnDragDataGet");
string tmp = "I'm data!";
byte[] b = new byte[tmp.Length];
for (int i=0; i<tmp.Length; ++i)
b[i] = (byte)tmp[i];
sdata.Set(sdata.Target, 8, b, tmp.Length);
}
protected override void OnDragDataReceived
(Gdk.DragContext context, int x, int y,
SelectionData sdata, uint info, uint time)
{
Console.WriteLine ("OnDragDataReceived");
int length = sdata.Length;
if ((length>=0) && (sdata.Format==8))
{
Console.WriteLine ("Received \"{0}\" in label",
sdata.Data.ToString());
}
Drag.Finish (context, false, false, time);
}
// main
public static void Main (string[] args)
{
Application.Init ();
new SharpApp();
Application.Run ();
}
}
}
but the result tells me I might be wrong.. I thought the button will be moved
when I drag it, but the button didn't move at all. Is there anyone able to fix my problem?
The following example prints into a label (called lblPath) the full path of the files dropped over it:
public partial class MainWindow: Gtk.Window
{
/** Add a label to your project called lblPath **/
public MainWindow () : base (Gtk.WindowType.Toplevel)
{
Build ();
//media type we'll accept
Gtk.TargetEntry [ ] target_table =
new TargetEntry [ ] {
new TargetEntry ("text/uri-list", 0, 0),
new TargetEntry ("application/x-monkey", 0, 1),
};
Gtk.Drag.DestSet (lblPath, DestDefaults.All, target_table, Gdk.DragAction.Copy);
lblPath.DragDataReceived += new Gtk.DragDataReceivedHandler(OnLabelDragDataReceived);
}
void OnLabelDragDataReceived (object sender, Gtk.DragDataReceivedArgs args)
{
if (args.SelectionData.Length > 0) {
byte[] data = args.SelectionData.Data;
string files = System.Text.Encoding.UTF8.GetString (data);
string file;
string[] fileArray = files.Split ('\n');
for (int i = 0; i < fileArray.Length - 1; i++) { //the last element is empty
file = fileArray [i].Replace ("\r", "");
if (file.StartsWith("file://"))
file = file.Substring(7); //for Windows should be 8
lblPath.Text += file + "\n";
}
}
}
}
Self answer
I found tutorials about drag and drop here:
https://github.com/mono/gtk-sharp/blob/master/sample/TestDnd.cs
http://my.safaribooksonline.com/book/programming/mono/0596007922/gtksharp/monoadn-chp-4-sect-8
and I made a tutorial of drag and drop myself.
This is drop file tutorial.
using System;
using System.Collections;
using System.Collections.Generic;
// 1. Drop file tutorial
namespace DropFile
{
public class App: Gtk.Window
{
Gtk.Label lbldrop;
public App (): base ("Drop file")
{
this.SetDefaultSize (250, 200);
this.SetPosition (Gtk.WindowPosition.Center);
this.DeleteEvent += OnTerminated;
this.lbldrop = new Gtk.Label ("Drop here!");
Gtk.Drag.DestSet (this.lbldrop, 0, null, 0);
this.lbldrop.DragDrop
+= new Gtk.DragDropHandler
(OnLabelDragDrop);
this.lbldrop.DragDataReceived
+= new Gtk.DragDataReceivedHandler
(OnLabelDragDataReceived);
Gtk.VBox vbox = new Gtk.VBox ();
vbox.PackStart (this.lbldrop, true, true, 0);
this.Add (vbox);
this.ShowAll ();
}
void OnLabelDragDrop (object sender, Gtk.DragDropArgs args)
{
Gtk.Drag.GetData
((Gtk.Widget)sender, args.Context,
args.Context.Targets[0], args.Time);
}
void OnLabelDragDataReceived
(object sender, Gtk.DragDataReceivedArgs args)
{
if (args.SelectionData.Length > 0
&& args.SelectionData.Format == 8) {
byte[] data = args.SelectionData.Data;
string encoded = System.Text.Encoding.UTF8.GetString (data);
// I don't know what last object is,
// but I tested and noticed that it is not
// a path
List<string> paths
= new List<string> (encoded.Split ('\r', '\n'));
paths.RemoveAll (string.IsNullOrEmpty);
paths.RemoveAt (paths.Count-1);
for (int i=0; i<paths.Count; ++i)
{
Console.WriteLine ("Path {0}: {1}", i, paths[i]);
}
}
}
bool Test (string str)
{
return true;
}
void OnTerminated (object sender, EventArgs args)
{
Gtk.Application.Quit ();
}
public static void Main (string[] args)
{
Gtk.Application.Init ();
new App ();
Gtk.Application.Run ();
}
}
}
And this is drag button tutorial.
using System;
// 2. Drag button tutorial
namespace DragButton
{
public class App: Gtk.Window
{
enum StatusType
{
Checked,
NotChecked
}
Gtk.Button btnDrag;
Gtk.Label lblDrop;
bool isChecked;
Gtk.Statusbar sBar;
public App (): base("Drag And Drop Complete")
{
this.SetDefaultSize (250, 200);
this.SetPosition (Gtk.WindowPosition.Center);
this.DeleteEvent += OnTerminated;
this.isChecked = false;
this.sBar = new Gtk.Statusbar ();
sBar.Push ((uint)StatusType.NotChecked, "Not checked");
this.btnDrag = new Gtk.Button ("Drag here");
Gtk.Drag.SourceSet
(this.btnDrag,
Gdk.ModifierType.Button1Mask
| Gdk.ModifierType.Button3Mask,
null,
Gdk.DragAction.Copy | Gdk.DragAction.Move);
this.btnDrag.DragDataGet
+= new Gtk.DragDataGetHandler
(HandleSourceDragDataGet);
this.btnDrag.DragDataDelete
+= new Gtk.DragDataDeleteHandler
(HandleSourceDragDataDelete);
// set drop label as destination
this.lblDrop = new Gtk.Label ("Drop here");
Gtk.Drag.DestSet (this.lblDrop, 0, null, 0);
this.lblDrop.DragMotion
+= new Gtk.DragMotionHandler
(HandleTargetDragMotion);
this.lblDrop.DragDrop
+= new Gtk.DragDropHandler
(HandleTargetDragDrop);
this.lblDrop.DragDataReceived
+= new Gtk.DragDataReceivedHandler
(this.HandleTargetDragDataReceived);
this.lblDrop.DragDrop
+= new Gtk.DragDropHandler
(this.HandleStatBarDragDrop);
Gtk.MenuBar bar = new Gtk.MenuBar ();
Gtk.MenuItem item = new Gtk.MenuItem ("File");
Gtk.Menu menu = new Gtk.Menu ();
item.Submenu = menu;
bar.Append (item);
// accel key
Gtk.AccelGroup ag = new Gtk.AccelGroup ();
this.AddAccelGroup (ag);
item = new Gtk.MenuItem ("Quit");
item.Activated += OnTerminated;
item.AddAccelerator
("activate", ag, new Gtk.AccelKey
(Gdk.Key.Q, Gdk.ModifierType.ControlMask,
Gtk.AccelFlags.Visible));
menu.Append (item);
Gtk.VBox vbox = new Gtk.VBox();
vbox.PackStart (bar, false, false, 0);
Gtk.HBox hbox = new Gtk.HBox ();
hbox.PackStart (this.btnDrag, true, true, 0);
hbox.PackStart (this.lblDrop, true, true, 0);
vbox.PackStart (hbox, true, true, 0);
vbox.PackStart (sBar, false, false, 0);
this.Add (vbox);
this.ShowAll ();
}
void OnTerminated(object sender, EventArgs args)
{
Gtk.Application.Quit ();
}
void HandleSourceDragDataGet
(object sender, Gtk.DragDataGetArgs args)
{
Console.WriteLine ("Source Drag Data Get");
args.SelectionData.Text = "I'm data!";
}
void HandleSourceDragDataDelete
(object sender, Gtk.DragDataDeleteArgs args)
{
Console.WriteLine ("Source Drag Data Delete");
Console.WriteLine ("Delete the data!");
}
void HandleTargetDragMotion
(object sender, Gtk.DragMotionArgs args)
{
Gdk.Drag.Status (args.Context,
args.Context.SuggestedAction,
args.Time);
args.RetVal = true;
}
void HandleTargetDragDrop
(object sender, Gtk.DragDropArgs args)
{
Console.WriteLine ("drop");
if (args.Context.Targets.Length != 0) {
Gtk.Drag.GetData
((Gtk.Widget)sender, args.Context,
args.Context.Targets[0], args.Time);
args.RetVal = true;
}
args.RetVal = false;
}
void HandleTargetDragDataReceived
(object sender, Gtk.DragDataReceivedArgs args)
{
Console.WriteLine ("received");
if (args.SelectionData.Length >= 0
&& args.SelectionData.Format == 8)
{
Console.WriteLine ("Hi!");
Gtk.Drag.Finish (args.Context, true, false, args.Time);
}
Gtk.Drag.Finish (args.Context, false, false, args.Time);
}
void HandleStatBarDragDrop
(object sender, Gtk.DragDropArgs args)
{
isChecked = !isChecked;
if (isChecked)
sBar.Push ((uint)StatusType.Checked, "Checked");
else
sBar.Pop ((uint)StatusType.Checked);
}
public static void Main (string[] args)
{
Gtk.Application.Init ();
new App ();
Gtk.Application.Run ();
}
}
}