স্থির সম্পত্তির সাথে আবদ্ধ


168

টেক্সটবক্সে একটি সাধারণ স্ট্যাটিক স্ট্রিং প্রপার্টি বাঁধতে আমার খুব কষ্ট হচ্ছে।

স্থির সম্পত্তি সহ শ্রেণিটি এখানে:

public class VersionManager
{
    private static string filterString;

    public static string FilterString
    {
        get { return filterString; }
        set { filterString = value; }
    }
}

আমার এক্সএএমএলে, আমি কেবল এই স্থিতিশীল সম্পত্তিটি একটি টেক্সটবক্সের সাথে আবদ্ধ করতে চাই:

<TextBox>
    <TextBox.Text>
        <Binding Source="{x:Static local:VersionManager.FilterString}"/>
    </TextBox.Text>
</TextBox>

সবকিছু সংকলন করে, তবে রান সময়ে, আমি নিম্নলিখিত ব্যতিক্রম পাই:

'উত্স' এট্রিবিউটের মানটি 'সিস্টেম. উইন্ডোজ.মার্কআপ.স্ট্যাটিক এক্সটেনশন' টাইপের বস্তুতে রূপান্তর করতে পারে না। মার্কআপ ফাইলটিতে 'সিস্টেম. উইন্ডোজ.ডাটা.বাইন্ডিং' অবজেক্টে ত্রুটি 'বার্নডিস্ক; উপাদান / সিলেক্টরওয়েশনপেজটি ফাংশন। এক্সামল' ​​লাইন 57 পজিশন 29।

আমি কি ভুল করছি কোন ধারণা?

উত্তর:


168

যদি বাইন্ডিংয়ের দ্বি-মুখী হওয়া দরকার হয় তবে আপনাকে অবশ্যই একটি পাথ সরবরাহ করতে হবে। স্থিতিশীল সম্পত্তিতে দ্বি-মুখী বাধ্যবাধকতা করার কৌশল রয়েছে, তবে শ্রেণিটি স্থির না থাকে: সংস্থানগুলিতে শ্রেণীর একটি নোংরা উদাহরণ ঘোষণা করুন, এবং এটি বাধ্যতামূলক উত্স হিসাবে ব্যবহার করুন।

<Window.Resources>
    <local:VersionManager x:Key="versionManager"/>
</Window.Resources>
...

<TextBox Text="{Binding Source={StaticResource versionManager}, Path=FilterString}"/>

এই উত্তরটি আমার ক্ষেত্রে আরও উপযুক্ত কারণ আমি আমার উত্স শ্রেণিতে DependencyObject প্রবর্তন করতে চাই না। বখশিশের জন্য ধন্যবাদ!
অ্যান্টনি ব্রায়েন

6
দ্রষ্টব্য যে আপনার পাঠ্য বাক্সটিকে মানটিকে স্থিতিশীল সম্পত্তিতে ফিরিয়ে আনতে সক্ষম করবে, তবে উত্সের মান পরিবর্তিত হলে পাঠ্যবক্সটি আপডেট করবে না।
অ্যাডাম সিলস

1
এটি ঠিক আছে, আমার কেবলমাত্র এই ক্ষেত্রে পাঠ্যবক্স থেকে উত্সটিতে বাঁধাই করা দরকার। আমি যদি বাঁধাইকে অন্যভাবে কাজ করতে চাই তবে আমি এই পদ্ধতির একটির প্রয়োজন সম্পর্কে অবগত। INotifyPropertyChanged, <PerertyName> পরিবর্তিত ইভেন্ট বা নির্ভরতা সম্পত্তি।
অ্যান্টনি ব্রায়েন

1
দ্রষ্টব্য: এই সমাধানটি কোনও এমভিভিএম পরিস্থিতিতে কাজ করবে না, যেহেতু সাধারণত আপনি যে ধরণের অবধি আবদ্ধ হন সেগুলির ধরণের অ্যাক্সেস আপনার কাছে নেই।
অ্যান্টনি উডস

@ থমাস আমার পক্ষে এটি কাজ করতে পছন্দ করবে তবে তা পারে না। আমি আমার দ্বিধাটি
অ্যান্ড্রু সিম্পসন

107

আপনি এর মতো স্ট্যাটিকের সাথে বাঁধতে পারবেন না। জড়িত নেই DependencyObject(বা বাস্তবায়িত বস্তুর উদাহরণ INotifyPropertyChanged) জড়িত না থাকায় বাধ্যতামূলক অবকাঠামোগত আপডেটগুলি সম্পর্কে অবহিত হওয়ার কোনও উপায় নেই ।

যদি সেই মানটি পরিবর্তন না হয়, তবে কেবল বাইন্ডিংটি খনন করে x:Staticসরাসরি Textসম্পত্তির অভ্যন্তরে ব্যবহার করুন । appভার্সনম্যানেজার শ্রেণীর নাম স্থান (এবং সমাবেশ) হতে নিচে সংজ্ঞায়িত করুন ।

<TextBox Text="{x:Static app:VersionManager.FilterString}" />

মানটি যদি পরিবর্তন হয় তবে আমি মানটি যুক্ত করতে একটি সিঙ্গলটন তৈরি করার পরামর্শ দিচ্ছি এবং এটির সাথে বাঁধাই।

সিঙ্গলটনের একটি উদাহরণ:

public class VersionManager : DependencyObject {
    public static readonly DependencyProperty FilterStringProperty =
        DependencyProperty.Register( "FilterString", typeof( string ),
        typeof( VersionManager ), new UIPropertyMetadata( "no version!" ) );
    public string FilterString {
        get { return (string) GetValue( FilterStringProperty ); }
        set { SetValue( FilterStringProperty, value ); }
    }

    public static VersionManager Instance { get; private set; }

    static VersionManager() {
        Instance = new VersionManager();
    }
}
<TextBox Text="{Binding Source={x:Static local:VersionManager.Instance},
                        Path=FilterString}"/>

5
সত্যি? আমি স্থিতিশীল ইন্ট 32 এর সাথে বাঁধতে সক্ষম হয়েছি M ম্যাক্সভ্যালু যা আমার নমুনার সাথে খুব মিল: <টেক্সটবক্স পাঠ্য = {বাইন্ডিং উত্স = {x: স্ট্যাটিক সিস: ইনট 32.ম্যাক্সভ্যালু Mode, মোড = ওয়ান ওয়ে} "/> Is কাজ হচ্ছে কারণ এটি
একতরফা

2
হ্যাঁ, যে কোনও দ্বিমুখী বাইন্ডিংয়ের জন্য বাঁধার উপর একটি প্যাস সম্পত্তির মান প্রয়োজন। উত্সটি এমন একটি বস্তু হওয়া দরকার যা পাথ দ্বারা বর্ণিত সম্পত্তি যুক্ত করে contains ওয়ানওয়ে নির্দিষ্ট করে সেই সীমাবদ্ধতা সরিয়ে দেয়।
আদম সিলস

এছাড়াও, দেরিতে আপডেটের জন্য দুঃখিত, তবে আমি একটি নমুনা সহ উপরের উত্তরটি আপডেট করেছি।
অ্যাডাম সিলস

কোনও স্ট্যাটিক স্ট্রিং বেঁধে দেওয়ার উপায় আছে কি? আমার একটি মুটিবাইন্ডিং রয়েছে এবং ইনপুটগুলির মধ্যে একটি স্থির স্ট্রিং।
নিতিন চৌধুরী চৌদ্দ

39

.NET 4.5 এ স্ট্যাটিক বৈশিষ্ট্যগুলিতে আবদ্ধ হওয়া সম্ভব, আরও পড়ুন

আপনি একটি ডেটা বাঁধাইয়ের উত্স হিসাবে স্থির বৈশিষ্ট্যগুলি ব্যবহার করতে পারেন। কোনও স্থির ইভেন্ট উত্থাপিত হলে সম্পত্তিটির মান পরিবর্তিত হলে ডেটা বাইন্ডিং ইঞ্জিন সনাক্ত করে। উদাহরণস্বরূপ, যদি সোমারস ক্লাস ক্লাসটি মাইপ্রোপার্টি নামে একটি স্ট্যাটিক সম্পত্তি সংজ্ঞায়িত করে, মাইপ্রোপার্টিটির মান পরিবর্তিত হলে উত্থাপিত একটি স্ট্যাটিক ইভেন্টকে সামার ক্লাস সংজ্ঞায়িত করতে পারে। স্থির ইভেন্ট নিম্নলিখিত স্বাক্ষরগুলির মধ্যে দুটি ব্যবহার করতে পারে:

public static event EventHandler MyPropertyChanged; 
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged; 

নোট করুন যে প্রথম ক্ষেত্রে, শ্রেণিটি প্রপার্টিনেমচ্যাঞ্জড নামে একটি স্ট্যাটিক ইভেন্ট প্রকাশ করে যা ইভেন্ট হ্যান্ডলারের ইভেন্ট ইভেন্টগুলি পাস করে। দ্বিতীয় ক্ষেত্রে, শ্রেণিটি স্ট্যাটিকপ্রপার্টি চেঞ্জড নামে একটি স্ট্যাটিক ইভেন্ট প্রকাশ করে যা ইভেন্ট হ্যান্ডলারের কাছে প্রপার্টিচেন্জড এভেন্টস পাস করে। স্থিতিশীল সম্পত্তি প্রয়োগকারী একটি শ্রেণি যে কোনও পদ্ধতি ব্যবহার করে সম্পত্তি-পরিবর্তন বিজ্ঞপ্তি বাড়াতে বেছে নিতে পারে।


কেউ আরও পড়তে চাইলে লিঙ্কটি এখানে। মাইক্রোসফ্ট এটি নামিয়েছে, তবে এটি এখানে ওয়েব সংরক্ষণাগারে রয়েছে। web.archive.org/web/20131129053934/http://msdn.microsoft.com/...
সি Tewalt

এই উত্তরটি আমাকে সঠিক দিকে নির্দেশ করেছে, তবে উদাহরণ ছাড়াই বিশদটি কার্যকর করতে এখনও কিছুটা সময় নিয়েছে। আমি মূল কোডের উপর ভিত্তি করে একটি উদাহরণ লিখেছি ।
ম্যাট

13

ডাব্লুপিএফ 4.5 হিসাবে আপনি সরাসরি স্থিতিশীল বৈশিষ্ট্যগুলিতে বাঁধতে পারেন এবং আপনার সম্পত্তি পরিবর্তিত হলে বাঁধাই স্বয়ংক্রিয়ভাবে আপডেট হতে পারে। বাঁধাই করা আপডেটগুলি ট্রিগার করতে আপনাকে ম্যানুয়ালি একটি পরিবর্তন ইভেন্ট ওয়্যার আপ করতে হবে।

public class VersionManager
{
    private static String _filterString;        

    /// <summary>
    /// A static property which you'd like to bind to
    /// </summary>
    public static String FilterString
    {
        get
        {
            return _filterString;
        }

        set
        {
            _filterString = value;

            // Raise a change event
            OnFilterStringChanged(EventArgs.Empty);
        }
    }

    // Declare a static event representing changes to your static property
    public static event EventHandler FilterStringChanged;

    // Raise the change event through this static method
    protected static void OnFilterStringChanged(EventArgs e)
    {
        EventHandler handler = FilterStringChanged;

        if (handler != null)
        {
            handler(null, e);
        }
    }

    static VersionManager()
    {
        // Set up an empty event handler
        FilterStringChanged += (sender, e) => { return; };
    }

}

এখন আপনি আপনার স্থিতিশীল সম্পত্তিটিকে অন্য যেকোনো একটি মতো বাঁধতে পারেন:

<TextBox Text="{Binding Path=(local:VersionManager.FilterString)}"/>

1
VersionManagerবর্গ স্ট্যাটিক হতে পারে এবং সবকিছু এখনও কাজ করে। পাথ সংজ্ঞাতে বন্ধনীগুলি নোট করুন Path=(local:VersionManager.FilterString)। কেউ কেন জানেন যে তাদের আসলে কেন প্রয়োজন হয়?
chviLadilav

2
পথের সংজ্ঞায়িত ধনুর্বন্ধনীগুলির প্রয়োজন কারণ সম্পত্তিটি
অচল

11

কোনও staticসম্পত্তি বাঁধার দুটি উপায় / সিনট্যাক্স হতে পারে । P যদি staticশ্রেণিতে একটি সম্পত্তি হয় MainWindowতবে তার bindingজন্য textboxহবে:

1।

<TextBox Text="{x:Static local:MainWindow.p}" />

2।

<TextBox Text="{Binding Source={x:Static local:MainWindow.p},Mode=OneTime}" />

9

আপনি ObjectDataProviderক্লাস এবং এটি MethodNameসম্পত্তি ব্যবহার করতে পারেন । এটি দেখতে এটি দেখতে পারেন:

<Window.Resources>
   <ObjectDataProvider x:Key="versionManager" ObjectType="{x:Type VersionManager}" MethodName="get_FilterString"></ObjectDataProvider>
</Window.Resources>

ঘোষিত অবজেক্ট ডেটা সরবরাহকারী এর মতো ব্যবহার করা যেতে পারে:

<TextBox Text="{Binding Source={StaticResource versionManager}}" />

8

আপনি যদি স্থানীয় সংস্থানগুলি ব্যবহার করে থাকেন তবে নীচে হিসাবে তাদের উল্লেখ করতে পারেন:

<TextBlock Text="{Binding Source={x:Static prop:Resources.PerUnitOfMeasure}}" TextWrapping="Wrap" TextAlignment="Center"/>

3

.NET 4.5 + এর জন্য ডান বৈকল্পিক

সি # কোড

public class VersionManager
{
    private static string filterString;

    public static string FilterString
    {
        get => filterString;
        set
        {
            if (filterString == value)
                return;

            filterString = value;

            StaticPropertyChanged?.Invoke(null, FilterStringPropertyEventArgs);
        }
    }

    private static readonly PropertyChangedEventArgs FilterStringPropertyEventArgs = new PropertyChangedEventArgs (nameof(FilterString));
    public static event PropertyChangedEventHandler StaticPropertyChanged;
}

এক্সএএমএল বাঁধাই (ধনুর্বন্ধনীগুলির প্রতি তাদের মনোযোগ (), {} নয়)

<TextBox Text="{Binding Path=(yournamespace:VersionManager.FilterString)}" />

ইভেন্টহ্যান্ডলারকে সঠিকভাবে কল করতে আপনার কোডে কিছুটা পরিবর্তন এনেছে।
মার্ক এ। ডোনোহো

প্রচুর বিভিন্ন সমাধানের চেষ্টা করেছে এবং এটি কাজ করেছে। প্রপার্টি চেঞ্জড এভেন্টহ্যান্ডলারটি আমার পক্ষে কাজ করেছে। চিয়ার্স।
এমগামেরজ

2

আমার প্রকল্প ক্যালকবাইন্ডিং দেখুন , যা আপনাকে স্ট্যাটিক বৈশিষ্ট্য, উত্স বৈশিষ্ট্য, ম্যাথ এবং অন্যান্য সহ পাথ সম্পত্তি মানগুলিতে জটিল অভিব্যক্তি লিখতে সরবরাহ করে। সুতরাং, আপনি এটি লিখতে পারেন:

<TextBox Text="{c:Binding local:VersionManager.FilterString}"/>

গুডলাক!


0

আপনি যদি ভাল কনভেনশনগুলি অনুসরণ করতে চান তবে এই উত্তরগুলি সবই ভাল তবে ওপি সাধারণ কিছু চাইছিল , যা আমিও জিআইআই ডিজাইনের ধরণগুলির সাথে আচরণ করার পরিবর্তে চেয়েছিলাম। যদি আপনি যা করতে চান তার মধ্যে যদি বেসিক জিইউআই অ্যাপ্লিকেশনটির স্ট্রিং থাকে তবে আপনি কোনও অভিনব বিষয় ছাড়াই অ্যাড-হক আপডেট করতে পারেন, আপনি কেবল এটি সরাসরি আপনার সি # উত্সে অ্যাক্সেস করতে পারবেন।

আসুন ধরা যাক আপনি সত্যিই একটি বেসিক ডাব্লুপিএফ অ্যাপ মেন উইন্ডো এক্সএএমএল পেয়েছেন,

<Window x:Class="MyWPFApp.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:MyWPFApp"
            mc:Ignorable="d"
            Title="MainWindow"
            Height="200"
            Width="400"
            Background="White" >
    <Grid>
        <TextBlock x:Name="textBlock"                   
                       Text=".."
                       HorizontalAlignment="Center"
                       VerticalAlignment="Top"
                       FontWeight="Bold"
                       FontFamily="Helvetica"
                       FontSize="16"
                       Foreground="Blue" Margin="0,10,0,0"
             />
        <Button x:Name="Find_Kilroy"
                    Content="Poke Kilroy"
                    Click="Button_Click_Poke_Kilroy"
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    FontFamily="Helvetica"
                    FontWeight="Bold"
                    FontSize="14"
                    Width="280"
            />
    </Grid>
</Window>

এটি দেখতে এরকম কিছু দেখাবে:

এখানে চিত্র বর্ণনা লিখুন

আপনার মেইন উইন্ডো এক্সএএমএল এর উত্সে, আপনার এমন কিছু থাকতে পারে যেখানে আমরা প্রত্যক্ষই textBlock.Text'গুলি get/ setকার্যকারিতার মাধ্যমে মান পরিবর্তন করতে যাচ্ছি :

using System.Windows;

namespace MyWPFApp
{
    public partial class MainWindow : Window
    {
        public MainWindow() { InitializeComponent(); }

        private void Button_Click_Poke_Kilroy(object sender, RoutedEventArgs e)
        {
            textBlock.Text = "              \\|||/\r\n" +
                             "              (o o) \r\n" +
                             "----ooO- (_) -Ooo----";
        }
    }
}

তারপরে আপনি বাটনে ক্লিক করে সেই ক্লিক ইভেন্টটি ট্রিগার করবেন, ভয়েলা! কিলরোয় হাজির :)

এখানে চিত্র বর্ণনা লিখুন


0

আর একটি সমাধান হ'ল একটি সাধারণ শ্রেণি তৈরি করা যা প্রপার্টি চেঞ্জারকে এভাবে প্রয়োগ করে

public class ViewProps : PropertyChanger
{
    private string _MyValue = string.Empty;
    public string MyValue
    {
        get { 
            return _MyValue
        }
        set
        {
            if (_MyValue == value)
            {
                return;
            }
            SetProperty(ref _MyValue, value);
        }
    }
}

তারপরে আপনি কোথাও কোথাও ক্লাসের স্থির উদাহরণ তৈরি করুন

public class MyClass
{
    private static ViewProps _ViewProps = null;
    public static ViewProps ViewProps
    {
        get
        {
            if (_ViewProps == null)
            {
                _ViewProps = new ViewProps();
            }
            return _ViewProps;
        }
    }
}

এবং এখন এটি স্থির সম্পত্তি হিসাবে ব্যবহার করুন

<TextBlock  Text="{x:Bind local:MyClass.ViewProps.MyValue, Mode=OneWay}"  />

এবং এখানে প্রপার্টি চেঞ্জার বাস্তবায়ন প্রয়োজন হয়

public abstract class PropertyChanger : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (object.Equals(storage, value)) return false;

        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

-1

লিনেস্ট উত্তর (। নেট 4.5 এবং পরবর্তী):

    static public event EventHandler FilterStringChanged;
    static string _filterString;
    static public string FilterString
    {
        get { return _filterString; }
        set
        {
            _filterString= value;
            FilterStringChanged?.Invoke(null, EventArgs.Empty);
        }
    }

এবং এক্সএএমএল:

    <TextBox Text="{Binding Path=(local:VersionManager.FilterString)}"/>

বন্ধনী অবহেলা করবেন না

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.