We want to upload the media to Amazon S3 via Sitecore & save the path of the uploaded media to the custom field.
So we created a custom field,which has a menu button to upload the media.
Here's my custom field class:
public class ExternalImage : Edit
{
public ExternalImage()
{
this.Class = "scContentControl";
}
public override void HandleMessage(Message message)
{
Assert.ArgumentNotNull(message, "message");
base.HandleMessage(message);
string name;
if (message["id"] == this.ID && (name = message.Name) != null)
{
if (name == "externalimage:open")
{
// Need help to open media upload popup here
}
}
}
}
UPDATE
After some research I came to know that I need to call/invoke the media:upload command within the code,so here is what I did(without any success ):
if (name == "externalimage:open")
{
string text = "media:upload(load=1,tofolder=1,id={3D6658D8-A0BF-4E75-B3E2-D050FABCF4E1})";
var item2 = Client.ContentDatabase.GetItem("{3D6658D8-A0BF-4E75-B3E2-D050FABCF4E1}");
Command command = CommandManager.GetCommand(text);
if (command == null)
{
SheerResponse.Alert(Translate.Text("Edit command not found."), new string[0]);
return;
}
CommandState commandState = CommandManager.QueryState(text, item2);
command.Execute(new CommandContext(item2));
return;
}
Related
At work, we have a custom form to submit PostItems in Public Folder.
Because they're in custom form and fields, I can't get them through ExtendedProperties. Every time I try to do that, the ExtendedProperties.Count == 0.
I've seen so many links, but for some reason, they're provided with GUID that doesn't make sense (As in, where did they get that GUID!?), and they're more revolved around Contacts and Calendars, but not PostItems.
The custom fields/columns are stored in an ItemClass called "IPM.Post.Special_Department_INBOX"
Links of examples I've looked at:
Bind custom extended property for existing appointment using EWS managed API 2.0
How to read custom field value
Viewing custom extended properties by using the EWS Managed API 2.0
If it helps, this is the code:
public class PublicFolder
{
public string DisplayName { get; set; }
public FolderId FolderID { get; set; }
public int Childs { get; set; }
}
private void DoMagic()
{
try
{
List<PublicFolder> RootFolders = new List<PublicFolder>();
ExchangeService ES = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
try
{
ES.Credentials = new WebCredentials("email#domain.com", "password");
ES.AutodiscoverUrl("email#domain.com");
Folder F = Folder.Bind(ES, WellKnownFolderName.PublicFoldersRoot);
F.Load();
foreach (Folder fol in F.FindFolders(new FolderView(F.ChildFolderCount)))
{
PublicFolder PF = new PublicFolder();
PF.DisplayName = fol.DisplayName;
PF.Childs = fol.ChildFolderCount;
PF.FolderID = fol.Id;
RootFolders.Add(PF);
}
foreach (PublicFolder PF in RootFolders)
{
Folder Q = Folder.Bind(ES, PF.FolderID);
{
if (Q.ChildFolderCount > 0)
{
Q.Load();
if (Q.DisplayName == "Special Department's Folder")
{
foreach (Folder W in Q.FindFolders(new FolderView(Q.ChildFolderCount)))
{
if (W.DisplayName == "Inbox Folder")
{
Folder R = Folder.Bind(ES, W.Id);
{
foreach (Item I in R.FindItems(new ItemView(R.TotalCount)))
{
//THIS IS WHERE I WANT TO GET ITEM'S CUSTOM FIELDS FROM CUSTOM FORM
}
}
}
}
}
}
}
}
}
catch (Exception E)
{
MessageBox.Show(E.Message);
}
}
}
when i try to set a specific Item in dataGrid , it changes all other item's values to that same value. I'm not sure if it's a bug or i done something wrong. Here is my code:
(Datagrid is in another window (Main window), so i called a function in that window to edit the value)
private void AAbutton1_Click(object sender, RoutedEventArgs e)
{
Account selected = new Account();
if (textBox2.Text != null)
selected.username = textBox2.Text;
if (textBox12.Text != null)
selected.password = textBox12.Text;
if (locationTxtBox2.Text != null)
selected.location = locationTxtBox2.Text;
MainWindow.Instance.editAccount(selected);
MainWindow.Instance.updateData();
MainWindow.Instance.needsSave = true;
}
And here is the function in the main window:
public void editAccount(Account acc)
{
Account acc2;
Account selected = (Account)dataGrid.SelectedItem;
acc2 = Manager.accounts.ElementAt(Manager.accounts.FindIndex(a=> a == selected));
acc2.username = acc.username;
acc2.password = acc.password;
acc2.location = acc.location;
}
I really couldn't find a solution for this problem.
And here is the Account class in case you need it:
public class Account
{
public String username { get; set; }
public String password { get; set; }
public String location { get; set; }
public Account(String username,String password, String location)
{
this.username = username;
this.password = password;
this.location = location;
}
public Account()
{
}
}
Just to mention , i use Mahapps.metro controls.
I was right! I read your mind.
This isn't a WPF question, a binding question, or a DataGrid question. It's a "how do references work in C#?" question. It's a good question.
On file load, you start with a list of encrypted Accounts, but in decryption, you copy all the decrypted properties of each one of the accounts into the same instance of Account, and add that one instance multiple times to the list. The decrypted ones are all the same instance. You start off OK, but then you go off the rails in DecryptAccounts().
Here's the bug:
public static void DecryptAccounts()
{
// Hmmm. What's he planning to do with this?
Account holder = new Account(null, null, null);
accounts.Clear();
foreach (Account acc in Encryptedaccounts)
{
// HERE IT IS. This is the same instance of holder on every
// iteration. After file load, every Account in accounts is the
// same object as every other.
// You need to create a new Account object for each account.
holder.username = Decrypt(acc.username, user.Decryptedpassword);
holder.password = Decrypt(acc.password, user.Decryptedpassword);
holder.location = Decrypt(acc.location, user.Decryptedpassword);
accounts.Add(holder);
}
}
public static void LoadFromFile()
{
if (File.Exists(Path.Combine(appdata, folder, file)))
{
Encryptedaccounts = JsonConvert.DeserializeObject<List<Account>>(File.ReadAllText(Path.Combine(appdata, folder, file)));
}
DecryptAccounts();
}
Here's the fix
Manager.cs
public Account DecryptAccount(Account acc)
{
return new Account {
username = Decrypt(acc.username, user.Decryptedpassword),
password = Decrypt(acc.password, user.Decryptedpassword),
location = Decrypt(acc.location, user.Decryptedpassword)
};
}
public static void DecryptAccounts()
{
accounts.Clear();
foreach (Account acc in Encryptedaccounts)
{
accounts.Add(DecryptAccount(acc));
}
}
// You've got the same issue here
private static void EncryptAccounts()
{
Encryptedaccounts.Clear();
foreach (Account acc in accounts)
{
Encryptedaccounts.Add(EncryptAccount(acc));
}
}
public Account EncryptAccount(Account acc)
{
return new Account {
username = Encrypt(acc.username, user.Decryptedpassword),
password = Encrypt(acc.password, user.Decryptedpassword),
location = Encrypt(acc.location, user.Decryptedpassword)
};
}
Some other issues here. Not bugs, but life will be easier if you do stuff the "proper WPF way":
Manager.accounts should be of type ObservableCollection<Account>. Then it will automatically notify the DataGrid whenever you add or remove items from it and you won't have to do this updateData() thing to manually refresh the grid all the time.
Manager and Account both ought to implement INotifyPropertyChanged and fire notifications on their properties when their values change. In C#6, this is very simple:
using System.Runtime.CompilerServices;
using System.ComponentModel;
// ... snip ...
public event PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
Then your properties look like this:
private String _username = null;
public String username {
get { return _username; }
set {
if (value != _username)
{
_username = value;
OnPropertyChanged();
}
}
}
When they do that, anything you bind them to in the UI will be notified whenever you change the values. You'll be able to set properties on the selected grid item and the UI will update without any grid refresh or anything -- it'll just know. Very convenient.
How I can refresh ParseUser.CurrentUser in Xamarin for iOS ?
There is no any method like refresh().
From the Parse forums:
ParseUser currentUser = ParseUser.getCurrentUser();
currentUser.fetchInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
ParseUser currUser = (ParseUser) object;
// Do Stuff with currUSer
} else {
// Failure!
}
}
});
Currently I'm implementing a Screen indicating wheater a module is not existing or still in development.
The Back Button has the following code:
regionNavigationService.Journal.GoBack();
This is working as expected. But the user is not coming from the Home Screen. So I need to access the View Name from the last Entry in Navigation Journal.
Example: User is coming from Settings Screen => The text should display "Back to Settings Screen"
Assuming the view name you are looking for is when you do new Uri("Main", UriKind.Relative) that you would want the word Main as the view name.
The forward and backward stacks in the RegionNavigationJournal are private. You could use reflection to get access to it.
var journal = regionNavigationService.Journal as RegionNavigationJournal;
if (journal != null)
{
var stack =
(Stack<IRegionNavigationJournalEntry>)
typeof (RegionNavigationJournal).GetField("backStack",
BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(journal);
var name = stack.Peek().Uri.OriginalString;
}
Or a better way is to implement your own IRegionNavigationJournal that is a wrapper around it. This is using Unity to constructor inject the default RegionNavigationJournal if using MEF you might need to put the ImportingConstructorAttribute on it.
public class RegionNavigationJournalWrapper : IRegionNavigationJournal
{
private readonly IRegionNavigationJournal _regionNavigationJournal;
private readonly Stack<Uri> _backStack = new Stack<Uri>();
// Constructor inject prism default RegionNavigationJournal to wrap
public RegionNavigationJournalWrapper(RegionNavigationJournal regionNavigationJournal)
{
_regionNavigationJournal = regionNavigationJournal;
}
public string PreviousViewName
{
get
{
if (_backStack.Count > 0)
{
return _backStack.Peek().OriginalString;
}
return String.Empty;
}
}
public bool CanGoBack
{
get { return _regionNavigationJournal.CanGoBack; }
}
public bool CanGoForward
{
get { return _regionNavigationJournal.CanGoForward; }
}
public void Clear()
{
_backStack.Clear();
_regionNavigationJournal.Clear();
}
public IRegionNavigationJournalEntry CurrentEntry
{
get { return _regionNavigationJournal.CurrentEntry; }
}
public void GoBack()
{
// Save current entry
var currentEntry = CurrentEntry;
// try and go back
_regionNavigationJournal.GoBack();
// if currententry isn't equal to previous entry then we moved back
if (CurrentEntry != currentEntry)
{
_backStack.Pop();
}
}
public void GoForward()
{
// Save current entry
var currentEntry = CurrentEntry;
// try and go forward
_regionNavigationJournal.GoForward();
// if currententry isn't equal to previous entry then we moved forward
if (currentEntry != null && CurrentEntry != currentEntry)
{
_backStack.Push(currentEntry.Uri);
}
}
public INavigateAsync NavigationTarget
{
get { return _regionNavigationJournal.NavigationTarget; }
set { _regionNavigationJournal.NavigationTarget = value; }
}
public void RecordNavigation(IRegionNavigationJournalEntry entry)
{
var currentEntry = CurrentEntry;
_regionNavigationJournal.RecordNavigation(entry);
// if currententry isn't equal to previous entry then we moved forward
if (currentEntry != null && CurrentEntry == entry)
{
_backStack.Push(currentEntry.Uri);
}
}
}
If using unity in your Prism Bootstrapper you will need to replace the default registration of the IRegionNavigationJournal
protected override void ConfigureContainer()
{
this.RegisterTypeIfMissing(typeof(IRegionNavigationJournal), typeof(RegionNavigationJournalWrapper), false);
base.ConfigureContainer();
}
If using MEF you will need to put the ExportAttribute on top of the RegionNavigationJournalWrapper
[Export(typeof(IRegionNavigationJournal))]
You can see http://msdn.microsoft.com/en-us/library/gg430866%28v=pandp.40%29.aspx for more information on replacing their default implementation with your own. Once you have the wrapper you will still need to cast it as RegionNavigationJournalWrapper to get access to the PreviousViewName so still not perfect or create an interface that RegionNavigationJournalWrapper also implements to cast to that to get you access to the PreviousViewName
I'm putting together a custom control flow SSIS task for the first time in C#. On my task UI editor I have a property grid and in one of the options I would like to be able to populate a drop down list of any task variables available as well as give the user the option of creating a new one. I've been researching for a few days and I have found some good examples on the forum but I'm a little lost now. My code as follows compiles and the editor displays a drop down list but its blank. After stepping through it, it appears to be down to this line:
taskHostProperty = context.Instance.GetType().GetProperty("TransferTask", typeof(TaskHost));The "TransferTask" being the name of my control flow task. I'm wondering if this is correct?
My full code for this is below.
//Property Grid Property
[Category("General"),
Description("Specifies the local Path for this task"),
Browsable(true),
ReadOnly(false),
DesignOnly(false),
TypeConverter(typeof(VariableConverter)),
DisplayName("Local Path")]
public string LocalPath
{
get
{
return this.stLocalPath;
}
set
{
dtsVariableService = serviceProvider.GetService(typeof(IDtsVariableService)) as IDtsVariableService;
dtsVariableService.PromptAndCreateVariable(parentWindow, dtsContainer,"Local Path","User",typeof(string));
this.stLocalPath = value;
}
}
//Variable Converter
internal class VariableConverter : TypeConverter
{
StandardValuesCollection svc = new StandardValuesCollection(new ArrayList());
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
TaskHost taskHost = null;
PropertyInfo taskHostProperty = null;
List<string> values = new List<string>();
values.Add(NEW_VARIABLE);
if (context == null)
{
return svc;
}
if (context.Instance == null)
{
return svc;
}
taskHostProperty = context.Instance.GetType().GetProperty("TransferTask", typeof(TaskHost));
if (taskHostProperty == null)
{
return svc;
}
taskHost = taskHostProperty.GetValue(context.Instance, null) as TaskHost;
foreach(Variable v in taskHost.Variables)
{
if (!v.SystemVariable && v.DataType == TypeCode.String)
{
values.Add(v.QualifiedName);
}
}
values.Sort();
return new StandardValuesCollection(values);
}
In the end I gave up trying to add the variables to a property grid and just created my own form. I used the following code to populate a combobox and after allowing the user to add a new SSIS variable. I refreshed the datasource. I would still like to know how to do this properly but I just didnt have the time to sit and work it out.
I used the following to first get the SSIS variables I needed, I'm able to add a new SSIS variable and I'm able to select the newly created one. I'm sure there is a better way of doing this but this works for now.
public ObservableCollection<string> FillVariableList()
{
ObservableCollection<string> variables = new ObservableCollection<string>();
variables.Add(string.Empty);
variables.Add(New_Variable);
foreach (Variable v in thetaskHost.Variables)
{
if (!v.SystemVariable && v.DataType == TypeCode.String && !variables.Contains(v.Name))
{
variables.Add(v.Name);
}
}
return variables;
}
And I used the following to allow the user to add a new SSIS variable or select an existing SSIS variable and to refresh the SSIS variable combobox.
private void cmbxVariables_SelectionChangeCommitted(object sender, EventArgs e)
{
if (cmbxVariables.Text == New_Variable)
{
try
{
DtsContainer dtsContainer = null;
dtsVariableServie = serviceProvider.GetService(typeof(IDtsVariableService)) as IDtsVariableService;
Variable var = dtsVariableServie.PromptAndCreateVariable(null, dtsContainer, "VariableName", "User", typeof(string));
if (!var.IsNull())
{
cmbxVariables.DataSource = null;
cmbxVariables.DataSource = FillVariableList();
}
}
catch (Exception exe)
{
MessageBox.Show(exe.ToString());
}
}
else
{
foreach (Variable v in thetaskHost.Variables)
{
if (v.Name == cmbxVariables.Text)
{
//Do something with the variable selected
break;
}
}
}
}