Can't change the label on an excel ribbon - excel-dna

I've got a problem trying to set a custom label on teh fly with a ribbon using Excel-DNA.
If I don't included the annotation "getLabel='GetLabel'" then the plugin loads fine. ie the ribbon tab is shown with 2 buttons andthe button callbacks work fine.
If I do inclue the property "getLabel='GetLabel'" then the plugin doesn't even load, ie onLoad isn't called and the ribbon tab doesn't show up in excel.
Can anyone see what I'm doing wrong here. I don't see any errors when running in the debugger.
Here is my DNA file. I've tried to base it off one of the samples so it's easier to follow.
<DnaLibrary Name="Emsx Addin" RuntimeVersion="v2.0">
<ExternalLibrary Path="EmsxExcelTech1.dll" />
<Reference AssemblyPath="System.Windows.Forms.dll" />
<!-- Some images that can be used in the Ribbon ui -->
<Image Name="M" Path="M.png" Pack="true" />
<CustomUI>
<customUI xmlns='http://schemas.microsoft.com/office/2009/07/customui' loadImage='LoadImage' onLoad='OnLoad'>
<ribbon>
<tabs>
<tab id='CustomTab' label='K2 Emsx' insertAfterMso='View'>
<group id='SampleGroup' label='Global Sheet Status'>
<button id='LoginCmd' label='Logon' image='M' onAction='OnLogonPressed' getLabel='GetLabel' />
<button id='BetaCmd' label='Use Beta Route' image='M' size='normal' onAction='RunTagMacro' tag='OnUseBetaRoutes' />
</group >
</tab>
</tabs>
</ribbon>
</customUI>
</CustomUI>
</DnaLibrary>
Here is my Ribbon derived C# file.
[ComVisible(true)]
public class EmsxRibbon : ExcelRibbon
{
private IRibbonUI ribbon = null;
public void OnLogonPressed(IRibbonControl control)
{
EmsxIntegration.Instance.Login();
MessageBox.Show("Hello from control " + control.Id);
if (ribbon != null)
{
ribbon.InvalidateControl(control.Id);
}
}
string GetLabel(IRibbonControl control)
{
if (control.Tag == "Logon")
{
return "Logon";
}
else
{
return "Logoff";
}
}
public static void OnUseBetaRoutes()
{
MessageBox.Show("Hello from 'ShowHelloMessage'.");
}
public void OnLoad(IRibbonUI ribbon)
{
this.ribbon = ribbon;
}
}

When you use the getLabel event, you should not use label property, so change
<button id='LoginCmd' label='Logon' image='M' onAction='OnLogonPressed' getLabel='GetLabel' />
to
<button id='LoginCmd' image='M' onAction='OnLogonPressed' getLabel='GetLabel' />
Hope this helps.

Related

I dont understand how to call Validation logic with Template 10 Validation

I've been trying to reproduce the simplest validation logic ever possible with template 10 validation, but I Just dont get it.
I have created my Model like the wiki at the example at github:
public class User : ValidatableModelBase
{
//public User()
//{
// FirstName = string.Empty;
// LastName = string.Empty;
// Validator = i =>
// {
// var u = i as User;
// if (string.IsNullOrEmpty(u.FirstName))
// u.Properties[nameof(u.FirstName)].Errors.Add("The first name is required");
// else if (u.FirstName.Length <= 3)
// u.Properties[nameof(u.FirstName)].Errors.Add("First Name must be greater than 3 chars.");
// if (string.IsNullOrEmpty(u.LastName))
// u.Properties[nameof(u.LastName)].Errors.Add("The last name is required");
// else if (u.LastName.Length <= 3)
// u.Properties[nameof(u.LastName)].Errors.Add("Last Name must be greater than 3 chars.");
// };
//}
public int Id { get; set; }
public string FirstName
{
get
{
return Read<string>();
}
set
{
Write(value);
}
}
public string LastName
{
get
{
return Read<string>();
}
set
{
Write(value);
}
}
public override string ToString() => $"{FirstName} {LastName}";
}
as you can see I've even created a constructor to initialize my Object, I commented out because I wanted to initialize the values at my ViewModel Constructor.
Then my view model is this:
public class MainPageViewModel : ViewModelBase
{
public MainPageViewModel()
{
User = new User
{
FirstName = string.Empty,
LastName = string.Empty,
Validator = i =>
{
var u = i as User;
if (string.IsNullOrEmpty(u.FirstName))
u.Properties[nameof(u.FirstName)].Errors.Add("The first name is required");
else if (u.FirstName.Length <= 3)
u.Properties[nameof(u.FirstName)].Errors.Add("First Name must be greater than 3 chars.");
if (string.IsNullOrEmpty(u.LastName))
u.Properties[nameof(u.LastName)].Errors.Add("The last name is required");
else if (u.LastName.Length <= 3)
u.Properties[nameof(u.LastName)].Errors.Add("Last Name must be greater than 3 chars.");
},
};
}
private User _User;
public User User
{
get { return _User; }
set { _User = value; }
}
public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> suspensionState)
{
User.Validate();
await Task.CompletedTask;
}
public override async Task OnNavigatingFromAsync(NavigatingEventArgs args)
{
args.Cancel = false;
await Task.CompletedTask;
}
public void GotoSettings() =>
NavigationService.Navigate(typeof(Views.SettingsPage), 0);
public void GotoPrivacy() =>
NavigationService.Navigate(typeof(Views.SettingsPage), 1);
public void GotoAbout() =>
NavigationService.Navigate(typeof(Views.SettingsPage), 2);
}
Now at my view all I have is this:
<Page x:Class="ValidationSample.Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Behaviors="using:Template10.Behaviors"
xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:controls="using:Template10.Controls"
xmlns:validate="using:Template10.Controls.Validation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:ValidationSample.Views"
xmlns:m="using:ValidationSample.Models"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:ValidationSample.ViewModels" mc:Ignorable="d">
<Page.DataContext>
<vm:MainPageViewModel x:Name="ViewModel" />
</Page.DataContext>
<RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AdaptiveVisualStateGroup">
<VisualState x:Name="VisualStateNarrow">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NarrowMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for narrow view -->
<!--<Setter Target="stateTextBox.Text" Value="Narrow Visual State" />-->
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateNormal">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NormalMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for normal view -->
<!--<Setter Target="stateTextBox.Text" Value="Normal Visual State" />-->
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateWide">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource WideMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for wide view -->
<!--<Setter Target="stateTextBox.Text" Value="Wide Visual State" />-->
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<controls:PageHeader x:Name="pageHeader" RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.AlignTopWithPanel="True" Text="Main Page">
<!-- secondary commands -->
<controls:PageHeader.SecondaryCommands>
<AppBarButton Click="{x:Bind ViewModel.GotoSettings}" Label="Settings" />
<AppBarButton Click="{x:Bind ViewModel.GotoPrivacy}" Label="Privacy" />
<AppBarButton Click="{x:Bind ViewModel.GotoAbout}" Label="About" />
</controls:PageHeader.SecondaryCommands>
</controls:PageHeader>
<validate:ControlWrapper PropertyName="FirstName"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.Below="pageHeader">
<TextBox Width="300"
Margin="12,0,0,0"
Header="First Name"
Text="{Binding FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</validate:ControlWrapper>
</RelativePanel>
As fas as I know I have the model with the ValidatableModelBase logic Applied, I do have the Validate:wrapper applied to the view, I've set the validator at the VM ctor or I could set it at model ctor.
My problem is where do i make the Calling logic???
Because I havent been able to trigger the UpdateSourceTrigger of my FirstName field.
What am i doing wrong??
To be more honest I dont know where to place the Validate method, because at the sample at github the validate method is call everytime you open the modal dialog window, but that is when you are navigating to that window and its field everytime they changed they are being validated, but in my case nothing happens, why?? Hopefully someone can help me out, since I'm new at template 10 and also at UWP.
Damn, I was so damn tired but my mistake was so god damn simple I forgot to set the DataContext at the Parent Panel, In this case I should had add DataContext ={Binding Model}
this at XAML within the relative panel or any other Panel.
I felt so noob to have made this question.

Nativescript how to make a if condition in View XML

Is there anyway to do a if condition in the XML file of nativescript? (without angular)
if
<Card:CardView class="cardStyle" margin="10" elevation="40" radius="5">
<Slider value="18" minValue="5" maxValue="30" />
</Card:CardView>
else
<Card:CardView class="cardStyle" margin="10" elevation="40" radius="5">
<Label text="Example" class="h3" margin="10" />
</Card:CardView>
What you could do is use a boolean property (which in its get function has the condition you want) and bind it to the visibility of the CardView.
Looks like you can show/hide from the template file using visibility:
In XML file: ie. 'sample-page.xml'
<Button text="{{ isShowing ? 'Hide Me' : 'Show Me' }}" tap="toggleShowing"/> <!-- Notice missing interpolation in Button tag -->
<Label text="Showing Hidden Element" visibility="{{ isShowing ? 'visible' : 'collapsed' }}"/>
In Page file: ie. 'sample-page.ts'
let model = new ViewModel();
// Event handler for Page 'loaded' event attached in main-page.xml
export function pageLoaded(args: observable.EventData) {
const page = <Page>args.object;
page.bindingContext = model;
}
export function toggleShowing() {
model.set('isShowing', !model.get('isShowing'));
}
In View Model: ie. 'sample-view-model.ts'
isShowing:boolean = false;
The only way I found to do to do this was to use the navigatingTo event of the page:
export function navigatingTo(args: EventData) {
let page = <Page>args.object;
var myLayout = <StackLayout>page.getViewById("myLayout");
if (condition) {
let segmentedBar = new SegmentedBar;
...
myLayout.addChild(segmentedBar);
}
else {
let button: Button = new Button;
...
myLayout.addChild(button);
}
No possibility in the template file :-/
It can be done using ng-container.For example
<ng-container *ngIf="true">Your logic here....</ng-container>

Primefaces how to toggle a dashboard widget/panel visibility using ajax?

I have a dashboard with a considerable number of widgets / panels which are working just fine.
I'm looking for a way to toggle the visibility of a specific one using a commandButton ction listener without having to refresh the page, i.e. via AJAX.
<p:dashboard id="board" model="#{dashboardBean.model}">
<!-- iteration code begins -->
<p:panel id="#{wdgt.code}" header="#{wdgt.title}">
<h:outputText value="One of the dozens of widgets" />
</p:panel>
<!-- iteration code ends -->
<p:panel id="staticWdgtId" header="Static Widget Initially Invisible" visible="false">
Some static content
</p:panel>
</p:dashboard>
Then in the backing bean, at some point this action needs to be fired via a commandButton or an actionListener...
public void showTheWidget() {
DashboardColumn dbc = this.model.getColumn(1);
dbc.getWidget(2); // does not get a widget object with a visibility attribute :((
// so that I could manipulate such as dbc.getWidget(2).setVisible(true);
}
Any ideas?
STATIC APPROACH
You can associate the panel with a boolean.
Panel
<p:panel id="staticWdgtId" header="Static Widget Initially Invisible"
visible="#{bean.panelShow}">
Some static content
</p:panel>
Button
<p:commandButton actionListener="#{bean.actionListener()}"
value="Button"
update=":staticWdgtId" />
Bean
public void actionListener() {
setShowPanel(true);
}
DYNAMIC APPROACH
Render all the panel with display: none
Dashboard
<p:dashboard id="board" model="#{dashboardBean.model}">
<p:panel id="#{wdgt.code}" header="#{wdgt.title}" style="display: none">
<h:outputText value="One of the dozens of widgets" />
</p:panel>
</p:dashboard>
remoteCommand
<p:remoteCommand name="panelsToShow"
actionListener="#{bean.panelsToShowAction()}"
oncomplete="handleComplete(xhr, status, args)" />
bean.panelsToShowAction() you need Gson
public void panelsToShowAction() {
List<String> panels = new ArrayList<String>();
//iterate over the panels you want to show, and put #{wdgt.code} which is the id of the panel
panels.add("Code1");//id
panels.add("Code2");//id
RequestContext requestContext = RequestContext.getCurrentInstance();
requestContext.addCallbackParam("panels", new Gson().toJson(panels));
}
JS
$(document).ready(function() {
panelsToShow();
})
function handleComplete(xhr, status, args) {
var panels = eval('(' + args.panels + ')');
for (var i = 0, len = panels.length; i < len; i++) {
$('#'+panels[i]).show();
}
}

ZK Upload Image and Show It

how to upload an image and show it on browser using button in zk. I have tried it but the uploaded image did not appear on the browser. please show me what's wrong with my code:
this is the zul file:
<?xml version="1.0" encoding="UTF-8"?>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<window id="win" use="simple.zkoss.project.WindowController">
<hbox>
<button id="uploadButton" label="Upload" upload="true" onUpload="win.uploadImage((UploadEvent) event)" />
<div id="image" width="100px" height="100px" />
</hbox>
</window>
and the class:
import org.zkoss.util.media.Media;
import org.zkoss.zk.ui.UiException;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.zul.Div;
import org.zkoss.zul.Fileupload;
import org.zkoss.zul.Image;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Window;
public class WindowController extends Window {
private Div image;
public void uploadImage(UploadEvent event) {
Media media = event.getMedia();
if (media instanceof org.zkoss.image.Image) {
Image im = new Image();
im.setContent((org.zkoss.image.Image) media);
im.setParent(image);
} else {
Messagebox.show(media + " is not an image", "Error", Messagebox.OK, Messagebox.ERROR);
}
}
}
the image just did not appear in 'div' tag, but when I choose another type of file (not an image) it shows the messagebox which means that the condition was right. thank you
The Div image is null. retrieve it with getFellow("image").
you need to add annotation above the onUpload method #Listen("onUpload=#uploadButton")
change the yor div by:
<image id="idBtn"/>
and your method:
public void onUpload$idBtn(UploadEvent event) {
Media media = event.getMedia();
if (media instanceof org.zkoss.image.Image) {
img_identificacion.setContent((org.zkoss.image.Image) media);
}
}

How to bind with dynamic resource and specifying a path

I want to bind to a resource (DynamicResource) and access properties on that resource, but is there a way to do that?
(I want to visualize the default values from constructor in the xaml editor in visual studio. Those cannot be seen when referencing an object through DataContext nor through a property added on my Window class...)
Not working xaml: (works in composer but not at runtime...)
<Window ... >
<Window.Resources>
<local:MyClass x:Key="myResource" />
</Window.Resources>
<StackPanel>
<Button Content="{Binding Source={DynamicResource myResource} Path=Property1}" />
<Button Content="{Binding Source={DynamicResource myResource} Path=Property2}" />
</StackPanel>
</Window>
with the class (which probably need to implement INotifyPropertyChanged):
public class MyClass
{
public MyClass()
{
this.Property1 = "Ok";
this.Property2 = "Cancel";
}
public string Property1 { get; set; }
public string Property2 { get; set; }
}
That's because the DynamicResource markup extension can only be used on a dependency property, because it will need to update it if the resource changes. And Binding.Source is not a dependency property...
As a workaround, you could set the DataContext of the button with the DynamicResource :
<Button DataContext="{DynamicResource myResource}" Content="{Binding Path=Property1}" />
<Button DataContext="{DynamicResource myResource}" Content="{Binding Path=Property2}" />
Abusing the DataContext of an unrelated object seems to be the easiest workaround.
In case you still need the DataContext of your control (MVVM anyone?), you can also create an invisible helper FrameworkElement elsewhere:
<FrameworkElement Visibility="Collapsed" x:Name="ControlBrushGetter" DataContext="
{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
and later refer to it by using the name in the binding:
<SolidColorBrush Opacity="0.8"
Color="{Binding ElementName=ControlBrushGetter, Path=DataContext.Color}" />
Your designer will quite likely complain about not being able to resolve "Color" in the context of "object", but it will work fine at runtime.

Resources