wpf dependency with ItemTemplate - c#

I need to display value of selected RibbonMenuButton in TextBlock below. Items of ribbonMenuButton are defined as ItemTemplate. How to define reference in Path? I marked it by "xxx"
<ribbon:RibbonMenuButton ItemsSource = "{Binding Path=CompaniesList.Companies}" x:Name="rbtnCompanies" Label="{x:Static resources:ConsoliaJPK.SELECT_COMPANY}" SmallImageSource="Resources/Images/Check32.png" Margin="16,0,-15.604,-0.264">
<RibbonMenuButton.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="tblCompany" Text="{Binding Path=Name}" PreviewMouseLeftButtonDown="tblCompany_PreviewMouseLeftButtonDown" >
</TextBlock>
</DataTemplate>
</RibbonMenuButton.ItemTemplate>
</ribbon:RibbonMenuButton>
<TextBlock Text = "{Binding ElementName=rbtnCompanies, Path=xxx}" Margin="41,6,-132,-6.604"></TextBlock>

I suppose rbtnCompanies.xxx should contain Name. You can do this assignment in your tblCompany_PreviewMouseLeftButtonDown I suppose.

Related

WPF tooltip Binding getting override when I set the tooltip from code

I have a User control and I bind the tooltip of that control into some object's property
<usercontrols:ucButton x:Name="xSaveCurrentBtn" ButtonType="ImageButton" ButtonFontImageSize="16" ButtonImageWidth="18" ButtonImageHeight="18" ButtonImageType="Save" Click="xSaveSelectedButton_Click" ButtonStyle="{StaticResource $ImageButtonStyle_Menu}" DockPanel.Dock="Right" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,0,0">
<usercontrols:ucButton.ToolTip>
<ToolTip Content="{Binding ItemName, Mode=OneWay}" ContentStringFormat="Save {0}"/>
</usercontrols:ucButton.ToolTip>
</usercontrols:ucButton>
from the code I set the data context of the ucButton to be my object:
xSaveCurrentBtn.DataContext = WorkSpace.Instance.CurrentSelectedItem;
sometimes the CurrentSelectedItem is null, and if this is the case I want the tooltip to display "No Item Selected"
I tried doing this:
xSaveCurrentBtn.Tooltip = "No Item Selected";
but when the CurrentSelectedItem isn't null and I reset the xSaveBtn.DataContext to that object, I am still seeing the No Item Selected tooltip as if my WPF tooltip section was overriden and its no longer binding into the datacontext ItemName Property
You are trying to set a property to two values at the same time. It's impossible.
What you are doing in XAML is equivalent to:
xSaveCurrentBtn.Tooltip = new ToolTip() {.....};
When you setting a string value to the same property, the previous value is lost. And it is not possible to restore it if you do not save it first.
You might want to assign a value in case of a binding error:
<ToolTip Content="{Binding ItemName,
Mode=OneWay,
FallbackValue='No Item Selected'}"
ContentStringFormat="Save {0}"/>
how can I bind the data context to update to be the new CurrentSelectedItem without explicitly setting it?
Assuming that «WorkSpace.Instance» is an immutable property that returns an instance of «WorkSpace» and «CurrentSelectedItem» is a property with an «INotifyPropertyChanged.PropertyChanged» notification, then you can do this:
<usercontrols:ucButton DataContext="{Binding CurrentSelectedItem, Source={x:Static viewmodels:WorkSpace.Instance}}" ...>
The «viewmodels» prefix depends on the assembly and namespace in which the «WorkSpace» class is declared.
you can use ContentTemplate with TextBlock, which will either use StringFormat, or TargetNullValue depending on ItemName being null:
<usercontrols:ucButton.ToolTip>
<ToolTip Content="{Binding ItemName}">
<ToolTip.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding StringFormat='Save {0}',
TargetNullValue='No Item Selected'}"/>
</DataTemplate>
</ToolTip.ContentTemplate>
</ToolTip>
</usercontrols:ucButton.ToolTip>
or if you bind Tooltip.Content differently:
<usercontrols:ucButton.ToolTip>
<ToolTip Content="{Binding}">
<ToolTip.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=ItemName,
StringFormat='Save {0}',
FallbackValue='No Item Selected'}"/>
</DataTemplate>
</ToolTip.ContentTemplate>
</ToolTip>
</usercontrols:ucButton.ToolTip>

How do I bind a comboBox to a different ItemsSource than it's parent DataGrid's ItemSource in a UWP project?

I am using MVVM and bind a DataGrid to an ObservableCollection<CustomClass>. I can successfully do that, however I want one of the DataGrid columns to be a ComboBox column, with items source List<ComboBoxValues>. Also another column must be a ToggleSwitch where a Command with parameter is fired when it's IsOn property changes value.
In the ViewModel:
public ObservableCollection<CustomClass> DataGridData { get; set; } = new ObservableCollection<CustomClass>();
public List<ComboBoxValues> ListValues { get; set; } = new List<ComboBoxValues>();
public MyICommand<ToggleSwitch> ToggleSwitchToggled_Command { get; private set; }
The problem I am getting is that the DataGrid's ItemsSource Binding is overriding the Binding path for the CombobBox's ItemsSource, as well as the Command's Binding. ListValues and ToggleSwitchToggled_Command is looked for within DataGridData.
For example:
Error: BindingExpression path error: 'ListValues' property not found on 'UWPProject.ViewModels.DataGridData'. BindingExpression: Path='ListValues' DataItem='UWPProject.ViewModels.DataGridData'; target element is 'Windows.UI.Xaml.Controls.ComboBox' (Name='null'); target property is 'ItemsSource' (type 'Object')
In Xaml:
<controls:DataGrid GridLinesVisibility="All"
AlternatingRowBackground="Gray" AutoGenerateColumns="False"
ItemsSource="{Binding DataGridData,Mode=TwoWay}">
<controls:DataGrid.Columns>
<controls:DataGridTextColumn Header="TextOne" Binding="{Binding aPropertyOneInDataGridData,Mode=TwoWay}"/>
<controls:DataGridTextColumn Header="TextTwo" Binding="{Binding aPropertyTwoInDataGridData,Mode=TwoWay}"/>
<controls:DataGridTemplateColumn Header="ComboBoxHeader">
<controls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<ComboBox ItemsSource="{Binding ListValues}"
SelectedValue="{Binding aPropertyThreeInDataGridData,Mode=TwoWay}"
PlaceholderText="Select Action">
</ComboBox>
</StackPanel>
</DataTemplate>
</controls:DataGridTemplateColumn.CellTemplate>
</controls:DataGridTemplateColumn>
<controls:DataGridTemplateColumn Header="ToggleSwitch_Header">
<controls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<ToggleSwitch x:Name="ToggelSwitch_Run"
IsOn="{Binding aPropertyFourInDataGridData,Mode=TwoWay}">
<interact:Interaction.Behaviors>
<interactcore:EventTriggerBehavior EventName="Toggled">
<interactcore:InvokeCommandAction Command="{Binding ToggleSwitchToggled_Command}"
CommandParameter="{Binding}"/>
</interactcore:EventTriggerBehavior>
</interact:Interaction.Behaviors>
</ToggleSwitch>
</StackPanel>
</DataTemplate>
</controls:DataGridTemplateColumn.CellTemplate>
</controls:DataGridTemplateColumn>
</controls:DataGrid.Columns>
</controls:DataGrid>
So I guess, the question is, how do I split the "source" or path where the Binding is looked for within the parent DataGrid. There are many WPF questions and answers on this, such as here and here. however I can't use DataContext, as I get the error that "DataContext is not supported in a UWP project." I can't find a solution for a UWP project for this problem. Also, I am using MVVM and no code behind, so I don't believe I can use x:Binding. I don't want to use code behind either.
Please help.
For your scenario, we suggest use DataGridComboBoxColumn to replace custom celltemplate. Then you could use x:bind markup extension to bind list property directly.
Because DataGridComboBoxColumn ItemsSource property could not access data source sub property directly, If you already make ListValues property for the Page class, you could also use x:bind to access like the following.
<controls:DataGridComboBoxColumn
Width="*"
Binding="{Binding p2}"
Header="Link"
ItemsSource="{x:Bind ListValues ,Mode=OneWay}"
Tag="Link"
/>
If you do want to make custom celltemplate, you could insert the ListValues property into your CustomClass. For more detail please refer this case reply.

Binding to Static class property and StringFormat

I am able to bind a static class property to a MenuItem header, but I cannot determine how to include a StringFormat so that I can display hard-coded text in addition to the property.
Is this possible?
Currently: (Displays "SQLSERVER1")
Header="{x:Static settings:Settings.CurrentServer}"
Desired: (Display "Connection: SQLSERVER1")
Header="{Binding Source={x:Static Settings:Settings.CurrentServer},StringFormat='Connection: {0}'}"
When I try the 'Desired' line in the XAML the StringFormat is ignored entirely. What am I doing wrong?
The following works for me as of .NET 5:
<Window Title="{Binding Source={x:Static vm:ApplicationSettings.ProductName}, StringFormat='{}{0} Document'}" />
where ProductName is defined as:
public static string ProductName {get { ... ; } }
MenuItem provides a HeaderStringFormat property that you should use:
<MenuItem Header="{Binding Source={x:Static Settings:Settings.CurrentServer}}"
HeaderStringFormat="Connection: {0}" />
Actually, that property is part of HeaderedItemsControl, which MenuItem happens to extend.
The StringFormat property is just ignored.
I suffered a similar problem and got around it by utilising ContentControl and it's separate ContentStringFormat property:
<TextBlock Cursor="Help" Text="Hello World" >
<TextBlock.ToolTip>
<ContentControl Content="{Binding Path=SomeProperty, Source={x:Static local:SomeStaticClass}}" ContentStringFormat="Hello {0}" />
</TextBlock.ToolTip>
</TextBlock>
StringFormat is disregarded for Content and Header, because their TargetType is not System.String. Those properties have corresponding *StringFormat properties to get around that limitation.

Binding the title of a LayoutDocument from a collection in AvalonDock 2.0

I'm binding an ObservableCollection to AvalonDock 2.0, where every item in the collection is an AvalonDock Document. This is how I do the binding:
<ad:DockingManager DocumentsSource="{Binding Path=OpenProjects, Mode=TwoWay}" ActiveContent="{Binding Path=CurrentProject, Mode=TwoWay}" LayoutItemTemplateSelector="{StaticResource ProjectTemplateSelector}">
...
</ad:DockingManager>
The problem is I want to show the Name of each item (which is specified in the property Name in CurrentProject) as the Document title. This is what I've tried:
<ad:DockingManager.DocumentHeaderTemplate>
<DataTemplate>
<TextBlock DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ad:DockingManager}, Path=ActiveContent, Mode=OneWay}" Text="{Binding Path=Name}" />
</DataTemplate>
</ad:DockingManager.DocumentHeaderTemplate>
This works fine if I only have one document open, but when I have several, they all show the Name of the current project. For example, if I have four open projects, with the names "A", "B", "C" and "D", if I'm currently viewing the document "C", all four tabs will show the title "C", and when I change to document "B", they will all change its names to "B".
Is there any way to prevent this changes? I've tried setting the binding mode to OneTime, but it doesn't seem to work.
What I ended up doing was as simple as this:
<ad:DockingManager.DocumentHeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Content.Name}" />
</DataTemplate>
</ad:DockingManager.DocumentHeaderTemplate>
Explanation: the DataContext for the binding inside the DocumentHeaderTemplate is the LayoutDocument itself. Turns out that it has a property, named Content, which represents de binding object inside each document (in this case, each Project inside my OpenProjects collection). In that object, I've got the property Name which is the string I want to use for the title.
This is because you are binding the title text to a property of the object referenced via the ActiveContent of your docking manager. It's obvious that changing the ActiveContent (focusing documents) will update the title of all LayoutDocument views to same value, because all titles are bound to same source.
You could try something like this:
<ad:DockingManager.DocumentHeaderTemplate>
<DataTemplate>
<Border x:Name="Header">
<ad:AnchorablePaneTitle Model="{Binding Model, RelativeSource={RelativeSource TemplatedParent}}"/>
</Border>
</DataTemplate>
</ad:DockingManager.DocumentHeaderTemplate>

WP7: Conditionally show & hide control elements in Data Templates

I have a note application with a ListBox control, which lists all the available notes from the ObservableCollection<Note> Notes. class Note has attributes like
String Title;
bool Has_Reminder;
DateTime Reminder_Date;
What I want is that the TextBlock element, which shows the Reminder_Date, is only shown, if Has_Reminder is true. But I do not know how to access this attribute from my custom control NoteListItem. Its this.DataContext attribute is null, but the control still properly displays the Note's bound attributes handed down by the ListBox ItemsSource. How can I achieve that?
Thanks for your help.
I tried to read the attributes in the constructor, which did not work:
public NoteListItem()
{
InitializeComponent();
Note this_note = LayoutRoot.DataContext as Note; // turns out, this_note is null
if (!this_note.Has_Reminder)
Reminder_Info.Visibility = System.Windows.Visibility.Collapsed;
}
NoteListItem control
<Grid x:Name="LayoutRoot" >
<TextBlock x:Name="Title" Text="{Binding Title}" />
<TextBlock x:Name="Reminder_Date" Text="{Binding Reminder_Date}" />
</Grid>
NoteList control:
<ListBox x:Name="NoteListBox" ItemsSource="{Binding Notes}" >
<ListBox.ItemTemplate>
<DataTemplate>
<local:NoteListItem />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Do you know how to use a converter? Your converter would convert a bool to a Visibility, then you can bind the TextBlock's Visibility to Has_Reminder:
<TextBlock x:Name="Reminder_Date" Text="{Binding Reminder_Date}" Visibility="{Binding Has_Reminder, Converter={...}}"/>
This might help: http://www.jeff.wilcox.name/2008/07/visibility-type-converter/

Categories

Resources