I have a message extension for MS Teams (based on Bot Framework v3). When I create a ThumbnailCard and return it to user, Teams inserts name and logo of my app to card. Can I remove them somehow?
This is how I create a card
var card = new ThumbnailCard { Text = "some text", Title= "title"};
Here is a screenshot:
No, the attribution on cards created by a messaging extension can't be removed by the app. Teams will automatically show it.
The ThumbnailCard object has the constructor:
/// <summary>
/// Initializes a new instance of the ThumbnailCard class.
/// </summary>
/// <param name="title">Title of the card</param>
/// <param name="subtitle">Subtitle of the card</param>
/// <param name="text">Text for the card</param>
/// <param name="images">Array of images for the card</param>
/// <param name="buttons">Set of actions applicable to the current
/// card</param>
/// <param name="tap">This action will be activated when user taps on
/// the card itself</param>
public ThumbnailCard(string title = default(string), string subtitle = default(string), string text = default(string), IList<CardImage> images = default(IList<CardImage>), IList<CardAction> buttons = default(IList<CardAction>), CardAction tap = default(CardAction))
{
Title = title;
Subtitle = subtitle;
Text = text;
Images = images;
Buttons = buttons;
Tap = tap;
CustomInit();
}
Have you tried with images = new List<CardImage>() ? same thing for buttons
Related
How to create a DataTemplate with code?
DataTemplate does not have a VisualTree property like in WPF.
The docu doesn't help either.
There is an IDataTemplateController, but it does not control anything. <ignorable>weird MAUI times again</ignorable>.
Found it in source code: There is a constructor parameter for a function which creates the view.
/// <Docs>
/// <param name="loadTemplate">A custom content generator to be called </param>
/// <summary>Creates and initializes a new instance of the <see cref="T:Microsoft.Maui.Controls.DataTemplate" /> class.</summary>
/// <remarks>To be added.</remarks>
/// </Docs>
public DataTemplate(Func<object> loadTemplate);
new DataTemplate(() => {
var label = new Label();
label.SetBinding(Label.TextProperty, new Binding("."));
return label;
});
There is currently a bug in Binding and you have to specify ".", a fix is merged.
I know i can use < para /> to create multiline function comments
/// <summary>
/// updates the car scrolling.<para />
/// there are also colors
/// <para />while clearall will remove all </summary>
/// <param name="status">optional to add a new car </param>
public void UpdateDrawing(int updatestatus = bgcar.color.none)
but that behaviour isnt like a linebreak \n it rather behaves like a double line brake ( \n\n ). Is there a way to have only a single line break.
So textblocks could be created for intellisence
Try this:
/// <summary>
/// <para>updates the car scrolling.</para>
/// <para>there are also colors</para>
/// <para>while clearall will remove all</para>
/// </summary>
I have a WPF xaml template and associated code behind with a variety of controls. The user can move these controls around so that one has the layout that one desires. However, once the user restarts the program, the controls return to their original locations. How do I make it so that the user can save the layout?
You can save, reload the layout (xaml):
After the user changes the layout [on Window Closing event], You can save a XAML file base changed layout using XamlWriter static class. In fact you serialize the container control and save it in a file.
Also you need some codes [in the window constructor after InitializeComponent()] to reload serialized layout of the container control [and its controls] from the file.
I put a sample (wrote by Matt Searles), here:
<StackPanel>
<WrapPanel x:Name="wrapPanel1" Height="200"></WrapPanel>
<Button Click="AddButton">Add Button</Button>
<Button Click="SaveButtons">Save Buttons</Button>
<Button Click="ReloadButtons">Reload Buttons</Button>
</StackPanel>
Code behind:
/// <summary>
/// Add a button to wrapPanel1
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AddButton(object sender, RoutedEventArgs e)
{
// Create the Button.
Button button = new Button();
button.Height = 50;
button.Width = 100;
button.Background = Brushes.AliceBlue;
button.Content = "Click Me";
wrapPanel1.Children.Add(button);
}
/// <summary>
/// Save wrapPanel1 to AA.xaml
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SaveButtons(object sender, RoutedEventArgs e)
{
StringBuilder outstr = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
settings.NewLineOnAttributes = true;
XamlDesignerSerializationManager dsm = new XamlDesignerSerializationManager(XmlWriter.Create(outstr, settings));
dsm.XamlWriterMode = XamlWriterMode.Expression;
XamlWriter.Save(wrapPanel1, dsm);
string savedControls = outstr.ToString();
File.WriteAllText(#"AA.xaml", savedControls);
}
/// <summary>
/// Reload the buttons in AA.xaml
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ReloadButtons(object sender, RoutedEventArgs e)
{
StreamReader sR = new StreamReader(#"AA.xaml");
string text = sR.ReadToEnd();
sR.Close();
StringReader stringReader = new StringReader(text);
XmlReader xmlReader = XmlReader.Create(stringReader);
WrapPanel wp = (WrapPanel)System.Windows.Markup.XamlReader.Load(xmlReader);
wrapPanel1.Children.Clear(); // clear the existing children
foreach (FrameworkElement child in wp.Children) // and for each child in the WrapPanel we just loaded (wp)
{
wrapPanel1.Children.Add(CloneFrameworkElement(child)); // clone the child and add it to our existing wrap panel
}
}
/// <summary>
/// Clone a framework element by serializing and deserializing it
/// </summary>
/// <param name="originalElement"></param>
/// <returns></returns>
FrameworkElement CloneFrameworkElement(FrameworkElement originalElement)
{
string elementString = XamlWriter.Save(originalElement);
StringReader stringReader = new StringReader(elementString);
XmlReader xmlReader = XmlReader.Create(stringReader);
FrameworkElement clonedElement = (FrameworkElement)XamlReader.Load(xmlReader);
return clonedElement;
}
So I've been digging into the whole SuspendLayout()/ResumeLayout() logic for a while now and I've been trying to implement it in the most efficient manner. One question I'm unable to find an answer for is that of which I've asked in the title : Does the BringToFront() method go before or after you call ResumeLayout()? Does it matter? My initial thought process is no, it doesn't matter, because it's only changing the z-index of the control and not effecting the control's layout, but I just want to be sure.
Here's block of code from my project where my question comes into play:
Note:This project runs on a Motorola MC65 mobile device and uses .net compact 3.5 framework
/// <summary>
/// Initializes the <see cref="VerifyReplacementPanel"/> class
/// </summary>
/// <param name="hostControl">The panel this control is being added to</param>
/// <param name="original">The product being replaced</param>
/// <param name="replacement">The product replacing with</param>
/// <param name="logHelper">The log helper interface</param>
public VerifyReplacementPanel(Control hostControl, ProductModel original, ProductModel replacement, ILogHelper logHelper)
{
hostControl.SuspendLayout();
SuspendLayout();
HostControl = hostControl;
Product = original;
Replacement = replacement;
_logHelper = logHelper;
Size = Size.FullScreen();
// original product panel
var panOrig = new blkPan(472, 75) { Location = new Point(4, 147), BackColor = Color.White };
var originalProductPanel = new ProductPanelArrayModel(panOrig, _logHelper);
originalProductPanel.AddPanelWithPic(original);
Controls.Add(panOrig);
// replacement product panel
var panRepl = new blkPan(472, 75) { Location = new Point(4, panOrig.B + 100), BackColor = Color.White };
var replacementProductPanel = new ProductPanelArrayModel(panRepl, _logHelper);
replacementProductPanel.AddPanelWithPic(replacement);
Controls.Add(panRepl);
// no button
var btnNo = new PushButton("No", ObjectName, true) { Location = new Point(38, Bottom - 93 - 36) };
btnNo.Click += btnNo_Click;
Controls.Add(btnNo);
_btnNoTop = btnNo.Top;
// yes button
var btnYes = new PushButton("Yes", ObjectName, true) { Location = new Point(259, btnNo.Top) };
btnYes.Click += btnYes_Click;
Controls.Add(btnYes);
ResumeLayout(false);
HostControl.Controls.Add(this);
BringToFront();
HostControl.ResumeLayout();
}
My question is interested in this section :
ResumeLayout(false);
HostControl.Controls.Add(this);
BringToFront();
HostControl.ResumeLayout();
Also, am I even using it correctly? Thank you for your time.
I'm currently facing a problem with printing a Plotmodel to an XPS-File.
What I have so far:
/// <summary>
/// Plotmodel to XPS-File
/// </summary>
/// <param name="model">The model</param>
/// <param name="fileName">The fileName</param>
/// <param name="width">Width of the model</param>
/// <param name="height">Height of the model</param>
public void Export(PlotModel model, string fileName, double width, double height)
{
try
{
using (Package xpsPackage = Package.Open(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var doc = new XpsDocument(xpsPackage))
{
var g = new Grid();
var p = new OxyPlot.Wpf.Plot { Model = model }; //Problem?
g.Children.Add(p);
var size = new Size(width, height);
g.Measure(size);
g.Arrange(new Rect(size));
g.UpdateLayout();
if (xpsdw == null) //XpsDocumentWriter xpsdw
xpsdw = XpsDocument.CreateXpsDocumentWriter(doc);
}
if (xpsdw != null)
{
xpsdw.Write(g);
}
}
}
}
This Code works fine (once), but the Problem is: No matter how often you use this method, you will always have just one Page with data. So if you want to print a second Plotmodel into the XPS-File the old one is deleted and you can only see the new one.
So the Question is:
Do you have an idea, how to append the new Plotmodel to the old XPS-File without overwriting it?
I also tried to use:
XpsExporter.Export(model, fileName, width, height);
instead of my function, but this didn't worked either.
If you know in advance that you will be writing multiple plots to a single file, you should look into VisualsToXpsDocument.
If you truly must append additional pages to an existing document on disk, it will be more difficult. You will need to dig down through the existing document to get to a FixedDocument (a child of the FixedDocumentSequence). Once you have the FixedDocument, you can add a new PageContent object to it. There is an example near the bottom of this thread.