Binding textblock text from resources wpf - c#

<Grid.Resources>
<DataTemplate x:Key="trackTemplateY">
<TextBlock x:Name="txbValueY" Text="{Binding ValueX}" Margin="5" FontSize="11" FontWeight="Medium"/>
</DataTemplate>
</Grid.Resources>
<TextBlock Text="{Binding ElementName=txbValueY,Mode=OneWay,Path=Text}"
Background="Orange" Foreground="White"/>
I try this above code but i cant to bind the text, how can i bind inside resources textblock text to outside the resources, Thanks

I am guessing that you are trying to show Text present in TextBlock resource in your second non-resource TextBlock.
You don't need DataTemplate. As you will progress ahead in WPF journey, you will come to know about those.
Below code will show "Resource Text" in your second TextBlock.
<Grid.Resources>
<TextBlock x:Key="TbRes1" Text="Resource Text" x:Name="txbValueY" Margin="5" FontSize="11" FontWeight="Medium"/>
</Grid.Resources>
<TextBlock Text="{Binding Source={StaticResource TbRes1},Mode=OneWay,Path=Text}"
Background="Orange" Foreground="White"/>

All sorts of problems here:
You're specifying Mode.TwoWay in your TextBlock Text binding, it should be Mode.OneWay.
You're binding to the Label's Text property. Label doesn't have a Text property, only Content. And it's not a dependency property so you can't bind to it. (That said, a fluke of the internal mechanics does cause it to appear to work under certain conditions).
A template is exactly that: a template. You can't bind to something that doesn't exist, so the binding is meaningless.
Maybe you could clarify exactly what it is you're trying to do so we can suggest an alternative way of achieving it? Specifically, show us exactly how you're instantiating that DataTemplate.
UPDATE:
You need the first textbox to be created in order for the second one to bind to it, simply declaring it inside a DataTemplate doesn't cause that to happen by itself, so the direct binding will fail. Binding UI elements together like this should generally be avoided though, why can't you simply give the second textbox the same binding as the first?
<Grid>
<Grid.Resources>
<DataTemplate x:Key="trackTemplateY">
<TextBlock x:Name="txbValueY" Text="{Binding ValueX}" Margin="5" FontSize="11" FontWeight="Medium"/>
</DataTemplate>
</Grid.Resources>
<TextBlock Text="{Binding ValueX}" Background="Orange" Foreground="White"/>
</Grid>
If for some reason this isn't possible then you can also create a binding proxy object (see this page for details):
<Grid>
<Grid.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding ValueX}" />
<DataTemplate x:Key="trackTemplateY">
<TextBlock x:Name="txbValueY" Text="{Binding ValueX}" Margin="5" FontSize="11" FontWeight="Medium"/>
</DataTemplate>
</Grid.Resources>
<TextBlock Text="{Binding Source={StaticResource ResourceKey=proxy}, Path=Data}" Background="Orange" Foreground="White"/>
</Grid>
Again, there are ways to bind to the data template declaration if you really want to, but to do that I'd have to see details of how your data template is being created at runtime.

Related

UWP Binding dot weird behaviour

I noticed a bit of a weird behaviour if i use a binding like
Text="{Binding ., Converter={StaticResource NavItemToCaptionConverter}}"
My Listview (Full List code below) doesnt show any text for this textblock. If i remove the "dot" at runtime the view updates and shows all items correct. but then i get a "Unexpected token 'Comma' on compile time.
The collection i am binding onto is a Observable collection filled with a few Enum items.
I Cant find where i made my mistake. Does anyone have an idea?
Here the full code for the ListView:
<ListView
Grid.Row="1"
Grid.Column="0"
HorizontalAlignment="Center"
ItemClick="OnNavigationBarItemClicked"
ItemsSource="{Binding NavigationBarItems}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Margin="10,15">
<Rectangle
Fill="DarkGray"
RadiusX="10"
RadiusY="10" />
<TextBlock
Margin="20,5"
FontSize="20"
Foreground="Black"
Text="{Binding ., Converter={StaticResource NavItemToCaptionConverter}}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The Binding Path=. is available for WPF. In general, we use Binding plus a space to bind the current context.
<TextBlock Margin="20,5"
FontSize="20"
Foreground="Black"
Text="{Binding Converter={StaticResource NavItemToCaptionConverter}}" />
If i remove the "dot" at runtime the view updates and shows all items
correct. But then i get a "Unexpected token 'Comma' on compile time.
When you remove the "dot" at runtime, it will just refresh by the content of Binding. But in compile time, it will check the complete xaml code and see if there are any syntax errors. So the 'comma' will give an error.

How to have multiple datatemplates in UWP ListView (x:bind)

I'm stuck with my UWP app, I'm trying to follow MVVM principle with {x:bind} instead of the older WPF way {binding name}
But I'm stuck with my idea/development, I'm trying insert multiple DataTemplates within ListView (or GridView).
I want to do something like this as an example:
<ListView.ItemTemplate>
<DataTemplate x:DataType="localModels:Cars">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Vertical">
<TextBlock Text="Name:" />
<TextBox Text="{x:Bind Name}" />
</StackPanel>
</StackPanel>
</DataTemplate>
<!-- Here is the second DataTemplate which isn't allowed in UWP -->
<DataTemplate x:DataType="localModels:Bikes">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Vertical">
<TextBlock Text="Name:" />
<TextBox Text="{x:Bind Name}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
As you can see, I have 2 DataTemplate: Cars and Bikes inside ListView.ItemTemplate.
Not sure if this is relevant: Cars.cs is inheriting from Bike.cs parent.
I don't really get why UWP doesn't accept more than 1 DataTemplate within ListView.ItemTemplate. Because I really want my ListView to show as many kind of data as possible.
What's the way to solve this issue in UWP and {x:bind}?
You can use a DataTemplateSelector to determine which datatemplate should be selected based on your data type. Here you can find an example.

ListBox Value Display in Windows Phone 8

I am trying to bind the observable collection with a ListBox and displaying the data on UI (Windows Phone 8.0).
My Listbox have four textblock for four property,
<ListBox x:Name="allListBox" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Style="{StaticResource txtBlockStyleDate}" Text="{Binding Date}"></TextBlock>
<TextBlock Style="{StaticResource txtBlockStyle1}" Text="{Binding TypeOfApproval}"></TextBlock>
<TextBlock Style="{StaticResource txtBlockStyle2}"
Text="{Binding TypeOfRequest}" />
<TextBlock Style="{StaticResource txtBlockStyle3}" Text="{Binding Status}"/>
<TextBlock Height="30"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
all the objects in observable collection are showing fine, but when any of the property does not have any value, its text block is still there, and its space is kind of visible, which gives the bad impression over UI.
Can you suggest what should i do, when any property is blank, textblock related to that should not eat any height and next textblock should take space of it.
I am attaching an image, see after testing blank space is visible, coz its property is null, i want to remove this space.
You are going to need an IValueConverter, basically the idea is you do this:
... insert ...
<ListBox.Resources>
<VisibilityConverter x:Key="VisibilityConverter"/>
</ListBox.Resources>
... change ...
<TextBlock Style="{StaticResource txtBlockStyleDate}" Visibility="{Binding Date, Converter={StaticResource VisibilityConverter}}" Text="{Binding Date}"/>
Within your IValueConverter implementation, you just see if the property is null or empty. If it is you just return Visibility.Collapsed
You need to use a Visibility converter for this!
If your bound data is text, a StringToVisibilityConverter would be fine.
An example on how to do this can be found here: http://www.smallandmighty.net/blog/using-value-converters-to-change-the-visibility-of-a-control

How to access a value in a TextBlock?

I have a window with the following elements, and I'm trying to access the value contained in <TextBlock Name="armingValue" but in my .xaml.cs file it doesn't seem to be recognised.
What do I need to do to access the value?
<Window.Resources>
<DataTemplate DataType="{x:Type ArmingVM:ArmingItem}">
<CheckBox Margin="10,5" IsChecked="{Binding IsSet}" Content="{Binding Name}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type ArmingVM:ArmingBindingData}">
<DockPanel>
<ItemsControl ItemsSource="{Binding ArmingItems}" HorizontalAlignment="Left">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<TextBlock Text="Enum Value: " HorizontalAlignment="Right"/>
<TextBlock Name="armingValue" Text="{Binding Value}" HorizontalAlignment="Right"/>
</DockPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="193*" />
<ColumnDefinition Width="551*" />
</Grid.ColumnDefinitions>
<Button Content="Get Panel Options" Name="btnGetOptionsConfigruation" Margin="12,12,23,396" Click="btnGetOptionsConfigruation_Click"></Button>
<StackPanel Grid.Column="1" Height="325" HorizontalAlignment="Left" Margin="68,43,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="438">
<ItemsControl Name="armingItemsControl" ItemsSource="{Binding}"/>
</StackPanel>
</Grid>
The backing variables generated by visual studio within the .xaml.cs file are only generated for certain circumstances. Any 'named' element within the body of a user control will have a generated backing variable. However, named elements within templates will not be generated. This is because Visual Studio has no way of knowing how your template will be used. For example, your template could be used by an ItemsControl to generate multiple template instances. What should be generated within .xaml.cs in that case?
You have two options:
Use binding, so that the state of your TextBlock.Text property is bound to a view model, so that you do not have to access the TextBlock element directly.
'walk' the visual tree to locate your TextBlock at runtime.
For (2), I would suggest using Linq-to-VisualTree, where you can find your TextBlock as follows:
TextBlock block = layoutRoot.Descendants<TextBlock>()
.Cast<TextBlock>().Where(tb => tb.Name="armingValue")
.Single();
You do not need to access TextBox value but its binded value.
So considering that you have in XAML
<TextBlock Name="armingValue" Text="{Binding Value}" HorizontalAlignment="Right"/>
You need to read a Value
Try always to avoid access UI elements directly in WPF, cause sometimes (not so rare cases) it becomes really tricky to find them if not imossible (I mean not guranteed way). Access a Data that stands behind them.
Maybe I did not get the point but why don't you create a binding to textbox and mark it as two way?
<TextBlock Text="Enum Value: " HorizontalAlignment="Right" Text="{Binding Value, Mode=TwoWay}"/>

WPF Listbox : How to bind data?

I have a listBox and add data to it like so:
for (int x = 0; x < Orchestrator.Instance.getTopicCount(); x++)
{
listTopics.Items.Add(Orchestrator.Instance.getTopic(x));
}
But I need to be able to do things like have text wrapping and divider lines, so I would like to do it the XAML.
Microsoft shows this:
<TextBlock Width="248" Height="24"
Text="{Binding ElementName=lbColor, Path=SelectedItem.Content,
Mode=OneWay}"
x:Name="tbSelectedColor"
Background="{Binding ElementName=lbColor, Path=SelectedItem.Content,
Mode=OneWay}"/>
But I don't really understand it. Here is my XAML:
<ListBox Height="261" HorizontalAlignment="Left" Margin="352,38,0,0" Name="listContent" VerticalAlignment="Top" Width="391" Grid.Column="1" HorizontalContentAlignment="Left" VerticalContentAlignment="Center" MaxWidth="391" ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
How am I able to achieve what I want? (Divider lines, text wrapping so I don't have to scroll horizontally, and data binding)
To specify the layout of each item, there are two different things you can change: the ItemContainerStyle, which provides the ControlTemplate used for each ListBoxItem, or the ItemTemplate, which provides the DataTemplate that is used to render each data item. The ItemTemplate is simpler to use if you're just getting started and haven't gotten the hang of ControlTemplates yet.
To get your text to wrap, there are two key things to do. Turn off the default horizontal scrolling of ListBox (which you got already), and set the TextWrapping property of your TextBlock to Wrap. To get to the TextBlock you need to define it in your ItemTemplate. Here's a simple example of the template declared inline, though you could also pull it out as a Resource. For the dividing line I used the simplest approach of a Border with only a bottom black line.
<ListBox x:Name="listContent" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,0,0,1" BorderBrush="Black">
<TextBlock Text="{Binding}" TextWrapping="Wrap"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
It seems that you will have to ascend the rather steep learning curve for how to use databinding in WPF first. Thereafter you should learn about DataTemplates and ItemTemplates to get the dividers and so forth.
Try this to get you started
A book I can heartily recommend is WPF in Action from Manning.
You need to define the ItemTemplate of your ListBox.
In your resources, add this:
<DataTemplate x:Key="myItemTemplate" TargetType="ListBoxItem">
<TextBlock Text="{Binding}"/>
</DataTemplate>
Supposing that your getTopic method returns a string, otherwise use {Binding MyTopicProperty} where MyTopicProperty is a property in your Topic class. Customize the TextBlock as you need.
Then use your ListBox like this:
<ListBox ItemTemplate="{StaticResource myItemTemplate"/>
here is an example how to bind listbox with RSS feed with DataTemplate:
<UserControl.Resources>
<XmlDataProvider x:Key ="DataRSS" XPath="//item" Source="http://rss.feedsportal.com/c/629/f/502199/index.rss">< /XmlDataProvider>
</UserControl.Resources>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<ListBox ItemsSource="{Binding Source={StaticResource DataRSS}}" Height="516" Margin="0,0,32,0" Background="{x:Null}" BorderBrush="#FF627DAE">
<ListBox.ItemTemplate >
<DataTemplate >
<Grid Width="400" Height="100" >
<Image Source="{Binding XPath=enclosure/#url}" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Top" />
<TextBlock TextWrapping="Wrap" Text="{Binding XPath=title}" FontWeight="Bold" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</grid>

Categories